namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Dapper;
    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Shared.EntityModels;

    using Hims.Shared.UserModels.Filters;

    /// <inheritdoc />
    public class RadiologyValueService : IRadiologyValueService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <summary>
        /// Initializes a new instance of the <see cref="RadiologyValueService"/> class.
        /// </summary>
        /// <param name="unitOfWork">
        /// The unit of work.
        /// </param>
        public RadiologyValueService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public Task<IEnumerable<RadiologyValueModel>> FetchAsync(RadiologyValueFilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (!string.IsNullOrEmpty(model.OrderCode))
            {
                where += $@" AND ""Code"" ILIKE '%{model.OrderCode}%'";
            }

            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", RADV.""RadiologyValueId"", RADV.""OrderCode"", RADV.""Code"", RADV.""Name"", RADV.""Test"", RADV.""CreatedDate"", 
                                RADV.""CreatedBy"", RAD.""RadiologyId"" ,RAD.""Name"" AS ""RadiologyName""  FROM ""RadiologyValue"" RADV
                                JOIN ""Radiology"" RAD ON RAD.""RadiologyId"" = RADV.""RadiologyId""
                                {where} Order by ""RadiologyValueId"" DESC";

            if (model.PageIndex <= 0)
            {
                return this.unitOfWork.Current.QueryAsync<RadiologyValueModel>(query);
            }

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);
            return this.unitOfWork.Current.QueryAsync<RadiologyValueModel>(query);
        }

        /// <inheritdoc />
        public async Task<int> AddAsync(RadiologyValueModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""RadiologyValueId"") FROM ""RadiologyValue"" WHERE ""OrderCode"" = '{model.OrderCode.Trim()}' AND ""RadiologyValueId"" <> {model.RadiologyValueId}");
            if (checkIf > 0)
            {
                return -1;
            }

            var radiologyValue = new RadiologyValue
            {
                OrderCode = model.OrderCode,
                Name = model.Name,
                Code = model.Code,
                Test = model.Test,
                RadiologyId = model.RadiologyId,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.UtcNow
            };

            return await this.unitOfWork.RadiologyValues.InsertAsync(radiologyValue);
        }

        /// <inheritdoc />
        public async Task<int> UpdateAsync(RadiologyValueModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""RadiologyValueId"") FROM ""RadiologyValue"" WHERE ""OrderCode"" = '{model.OrderCode}' AND ""RadiologyValueId"" <> {model.RadiologyValueId}");
            if (checkIf > 0)
            {
                return -1;
            }

            var radiologyValue = await this.unitOfWork.RadiologyValues.FindAsync(m => m.RadiologyValueId == model.RadiologyValueId);
            radiologyValue.RadiologyValueId = model.RadiologyValueId;
            radiologyValue.OrderCode = model.OrderCode?.Trim();
            radiologyValue.Name = model.Name;
            radiologyValue.Code = model.Code;
            radiologyValue.Test = model.Test;
            radiologyValue.RadiologyId = model.RadiologyId;
            radiologyValue.ModifiedBy = model.ModifiedBy;
            radiologyValue.ModifiedDate = DateTime.UtcNow;

            return await this.unitOfWork.RadiologyValues.UpdateAsync(radiologyValue);
        }

        /// <inheritdoc />
        public Task<int> DeleteAsync(int radiologyValueId)
        {
            var query = $@"DELETE FROM ""RadiologyValue"" WHERE ""RadiologyValueId""= {radiologyValueId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public Task<int> updateProviderEncounterAsync(int radiologyValueId)
        {
            var query = $@"UPDATE ""ProviderEncounter""   SET ""RadiologyValueIds"" = array_to_string(array_remove(string_to_array(""RadiologyValueIds"",','), '{radiologyValueId}'),',') ";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }
    }
}