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

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

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

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

            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 ""ScanLog"" 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 ""ScanLogType"" plt ON plt.""ScanLogTypeId"" = log.""ScanLogTypeId"" AND plt.""Active"" IS TRUE
                        {where} Order by log.""ScanLogId"" DESC";

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

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

        /// <inheritdoc />
        public async Task LogAsync(ScanLogModel model)
        {
            try
            {
                var ScanLog = new ScanLog
                {
                    LogDate = DateTime.UtcNow,
                    AccountId = model.AccountId,
                    LogFrom = model.LogFrom,
                    ScanLogTypeId = model.ScanLogTypeId,
                    LogDescription = model.LogDescription,
                    LocationId = model.LocationId
                };

                var a = await this.unitOfWork.ScanLogs.InsertAsync(ScanLog);
                return;
            }
            catch (Exception e)
            {
                e.Message.ToString();
                throw;
            }
        }
    }
}