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 LabLogServices : ILabLogService
    {
        /// <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 LabLogServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

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

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

            if (model.LocationId > 0)
            {
                where += $@" AND log.""LocationId"" = {model.LocationId}";
            }

            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 COUNT(*) OVER() AS ""TotalItems"", log.*, acc.""FullName"", rl.""RoleName"", plt.""LogTypeName"" FROM ""LabLog"" log
                        LEFT JOIN ""Account"" acc ON acc.""AccountId"" = log.""AccountId"" AND acc.""Active"" IS TRUE
                        LEFT JOIN ""Role"" rl ON rl.""RoleId"" = acc.""RoleId"" AND rl.""Active"" IS TRUE
                        LEFT JOIN ""LabLogType"" plt ON plt.""LabLogTypeId"" = log.""LabLogTypeId"" AND plt.""Active"" IS TRUE
                        {where} Order by log.""LabLogId"" DESC";

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

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

        /// <inheritdoc />
        public Task LogAsync(LabLogModel model)
        {
            var labLog = new LabLog
            {
                LogDate = DateTime.UtcNow,
                AccountId = model.AccountId,
                LogFrom = model.LogFrom,
                LabLogTypeId = model.LabLogTypeId,
                LogDescription = model.LogDescription,
                LocationId=model.LocationId
            };

            return this.unitOfWork.LabLogs.InsertAsync(labLog);
        }
    }
}