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;

    using Hims.Domain.Configurations;

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

        /// <summary>
        /// The amazon s 3 configuration.
        /// </summary>
        private readonly IAmazonS3Configuration amazonS3Configuration;


        /// <inheritdoc cref="IServiceService" />
        public ServiceServices(IUnitOfWork unitOfWork, IAmazonS3Configuration amazonS3Configuration)
        {
            this.unitOfWork = unitOfWork;
            this.amazonS3Configuration = amazonS3Configuration;
        }

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

            if (model.Active != null)
            {
                where += $@" AND s.""Active"" IS {((bool)model.Active ? "TRUE" : "FALSE")}";
            }

            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", s.*,(case when I.""IconName"" is not null then CONCAT('{this.amazonS3Configuration.BucketURL}',I.""IconName"") else null end )  AS ""Url"",
                        cra.""FullName"" AS ""CreatedByName"", mdf.""FullName"" AS ""ModifiedByName"" FROM ""Service"" s
                        LEFT JOIN ""Account"" cra ON cra.""AccountId"" = s.""CreatedBy"" AND cra.""Active"" IS TRUE  
                        LEFT JOIN ""Account"" mdf ON mdf.""AccountId"" = s.""ModifiedBy"" AND mdf.""Active"" IS TRUE
                        left join ""Icons"" I on I.""IconsId"" = s.""ServiceIconId""
                         {where} Order by ""ServiceId"" DESC";

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

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

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

            var service = new Service
            {
                Active = model.Active,
                ServiceName = model.ServiceName.Trim(),
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.UtcNow,
                ServiceIconId = model.ServiceIconId,
                ServiceJson = model.ServiceJson,
                Priority = model.Priority
            };

            return await this.unitOfWork.Services.InsertAsync(service);
        }

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

            var service = await this.unitOfWork.Services.FindAsync(m => m.ServiceId == model.ServiceId);
            service.ServiceName = model.ServiceName.Trim();
            service.ModifiedBy = model.ModifiedBy;
            service.ModifiedDate = DateTime.UtcNow;
            service.ServiceJson = model.ServiceJson;
            service.ServiceIconId = model.ServiceIconId;
            service.Active = model.Active;
            service.Priority = model.Priority;

            return await this.unitOfWork.Services.UpdateAsync(service);
        }

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

        /// <inheritdoc />
        public Task<int> ModifyStatusAsync(int serviceId, int modifiedBy, bool status)
        {
            var query = $@"UPDATE ""Service"" SET ""Active"" = {!status}, ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""ServiceId""= {serviceId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<ServiceModel>> FindAsync(string serviceIds)
        {
            var where = " WHERE ";
            if (!string.IsNullOrEmpty(serviceIds))
            {
                where += $@" ""ServiceId"" in ({serviceIds})";
            }

            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", s.* FROM ""Service"" s
                        LEFT JOIN ""Account"" cra ON cra.""AccountId"" = s.""CreatedBy"" AND cra.""Active"" IS TRUE  
                        LEFT JOIN ""Account"" mdf ON mdf.""AccountId"" = s.""ModifiedBy"" AND mdf.""Active"" IS TRUE {where}";
            return this.unitOfWork.Current.QueryAsync<ServiceModel>(query);
        }

        public async Task<string> FindNameByPackageId(int serviceid)
        {
            var query = $@"SELECT ""Name"" FROM ""Package"" WHERE ""PackageId"" = {serviceid}";
            var response = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>(query);
                return response;
        }
     

    }
}