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

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

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

            if (model.InventoryLogTypeId!= null)
            {
                where += $@" AND log.""InventoryLogTypeId"" = '{model.InventoryLogTypeId}'";
            }
            if (model.RoleId != null)
            {
                where += $@" AND rl.""RoleId"" = '{model.RoleId}'";
            }

            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";
            }

            if (!string.IsNullOrEmpty(model.RoleName))
            {
                where += $@" AND rl.""RoleName"" ILIKE '%{model.RoleName}%'";
            }
            if (!string.IsNullOrEmpty(model.FullName))
            {
                where += $@" AND acc.""FullName"" ILIKE '%{model.FullName}%'";
            }
            if (!string.IsNullOrEmpty(model.LogTypeName))
            {
                where += $@" AND lkp.""LogTypeName"" ILIKE '%{model.LogTypeName}%'";
            }

            var query = $@"SELECT COUNT(*) OVER() AS ""TotalItems"", log.*, acc.""FullName"", rl.""RoleName"",rl.""RoleId"", ilt.""LogTypeName""
                        FROM ""InventoryLog"" 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 ""InventoryLogType"" ilt ON ilt.""InventoryLogTypeId"" = log.""InventoryLogTypeId"" AND ilt.""Active"" IS TRUE
                        {where} Order by log.""InventoryLogId"" DESC";

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

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

        /// <inheritdoc />
        public Task LogAsync(InventoryLogModel model)
        {
            var inventoryLog = new InventoryLog
            {
                LogDate = DateTime.UtcNow,
                AccountId = model.AccountId,
                LogFrom = model.LogFrom,
                InventoryLogTypeId = model.InventoryLogTypeId,
                LogDescription = model.LogDescription
            };

            return this.unitOfWork.InventoryLogs.InsertAsync(inventoryLog);
        }
    }
}