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 GeneralAdviceServices : IGeneralAdviceService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc cref="IGeneralAdviceService" />
        public GeneralAdviceServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

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

            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", ""GeneralAdviceId"", ""FullName"", ""Description"", ""CreatedDate"", ""ModifiedDate"" FROM ""GeneralAdvice"" {where} Order by ""GeneralAdviceId"" DESC";

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

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

        /// <inheritdoc />
        public async Task<int> AddAsync(GeneralAdviceModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""GeneralAdviceId"") FROM ""GeneralAdvice"" WHERE TRIM(UPPER(""FullName"")) = '{model.FullName?.ToUpper().Trim()}'");
            if (checkIf > 0)
            {
                return -1;
            }

            var generalAdvice = new GeneralAdvice
            {
                FullName = model.FullName?.Trim(),
                Description = model.Description,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.UtcNow
            };

            return await this.unitOfWork.GeneralAdvices.InsertAsync(generalAdvice);
        }

        /// <inheritdoc />
        public async Task<int> UpdateAsync(GeneralAdviceModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""GeneralAdviceId"") FROM ""GeneralAdvice"" WHERE TRIM(UPPER(""FullName"")) = '{model.FullName?.ToUpper().Trim()}' AND ""GeneralAdviceId"" <> {model.GeneralAdviceId}");
            if (checkIf > 0)
            {
                return -1;
            }

            var generalAdvice = await this.unitOfWork.GeneralAdvices.FindAsync(m => m.GeneralAdviceId == model.GeneralAdviceId);
            generalAdvice.GeneralAdviceId = model.GeneralAdviceId;
            generalAdvice.FullName = model.FullName?.Trim();
            generalAdvice.Description = model.Description;
            generalAdvice.ModifiedBy = model.ModifiedBy;
            generalAdvice.ModifiedDate = DateTime.UtcNow;

            return await this.unitOfWork.GeneralAdvices.UpdateAsync(generalAdvice);
        }

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

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