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 Shared.UserModels.Filters;

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

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

        /// <inheritdoc />
        public Task<IEnumerable<PharmacyLogModel>> FetchAsync(PharmacyLogFilterModel model)
        {
            var where = $@" WHERE 1 = 1 ";

            if (model.PharmacyLogTypeId != null)
            {
                where += $@" AND log.""PharmacyLogTypeId"" = {model.PharmacyLogTypeId}";
            }

            if (model.AccountId != null)
            {
                where += $@" AND log.""AccountId"" = {model.AccountId}";
            }

            if (!string.IsNullOrEmpty(model.Description))
            {
                where += $@" AND log.""LogDescription"" ILIKE '%{model.Description}%'";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && !string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND (""LogDate"" at time zone 'UTC' at time zone 'Asia/Kolkata')::DATE >= '{model.FromDate}'::DATE";
                where += $@" AND (""LogDate"" at time zone 'UTC' at time zone 'Asia/Kolkata')::DATE <= '{model.ToDate}'::DATE";
            }      
            var query = $@" SELECT distinct COUNT(*) OVER() AS ""TotalItems"", lg.*,acc.""FullName"", rl.""RoleName"",plt.""LogTypeName""
                            from ""PharmacyLog"" lg JOIN ""PharmacyLogType"" plt ON plt.""PharmacyLogTypeId"" = lg.""PharmacyLogTypeId""
                            left JOIN ""Account"" acc ON acc.""AccountId"" = lg.""AccountId"" AND acc.""Active"" IS TRUE
                            left JOIN ""Role"" rl ON rl.""RoleId"" = acc.""RoleId"" AND rl.""Active"" IS TRUE
                        {where} Order by lg.""PharmacyLogId"" DESC";

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

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

        /// <inheritdoc />
        public Task LogAsync(PharmacyLogModel model)
        {
            var pharmacyLog = new PharmacyLog
            {
                LogDate = DateTime.UtcNow,
                AccountId = model.AccountId,
                LogFrom = model.LogFrom,
                PharmacyLogTypeId = model.PharmacyLogTypeId,
                LogDescription = model.LogDescription,
                LocationId=model.LocationId
            };

            return this.unitOfWork.PharmacyLogs.InsertAsync(pharmacyLog);
        }
    }
}