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

        /// <inheritdoc cref="IChargeGroupService" />
        public ChargeGroupService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public Task<IEnumerable<ChargeGroupModel>> FetchAsync(ChargeGroupFilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (!string.IsNullOrEmpty(model.ChargeGroupName))
            {
                where += $@" AND TRIM(UPPER(""ChargeGroupName"")) = '{model.ChargeGroupName.Trim().ToUpper()}'";
            }

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

            var query = $@"
                          select  Count(*) OVER() AS ""TotalItems"", d.""DepartmentId"",d.""DepartmentName"", cg.""ChargeGroupName"",  cg.""ChargeGroupId"", cg.""Active"",cg.""CreatedDate"" from ""ChargeGroup"" cg
                           left join ""Department"" d on cg.""DepartmentId"" = d.""DepartmentId""
                           {where} order by d.""DepartmentId""  ";

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

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

        /// <inheritdoc />
        public async Task<int> AddAsync(ChargeGroupModel model)
        {
            try
            {
                var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""ChargeGroupId"") FROM ""ChargeGroup"" WHERE ""DepartmentId"" = {model.DepartmentId} AND TRIM(UPPER(""ChargeGroupName"")) = '{model.ChargeGroupName.ToUpper().Trim()}'");
                if (checkIf > 0)
                {
                    return -1;
                }

                var chargeGroup = new ChargeGroup
                {
                    Active = true,
                    ChargeGroupName = model.ChargeGroupName,
                    DepartmentId = model.DepartmentId,
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.UtcNow,
                };

                return await this.unitOfWork.ChargeGroups.InsertAsync(chargeGroup);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message.ToString());
            }

            return 0;
        }


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

            var chargeGroup = await this.unitOfWork.ChargeGroups.FindAsync(m => m.ChargeGroupId == model.ChargeGroupId);
            chargeGroup.ChargeGroupName = model.ChargeGroupName;
            chargeGroup.Active = true;
            chargeGroup.DepartmentId = model.DepartmentId;
            chargeGroup.ModifiedBy = model.ModifiedBy;
            chargeGroup.ModifiedDate = DateTime.UtcNow;
            return await this.unitOfWork.ChargeGroups.UpdateAsync(chargeGroup);
        }

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

        /// <inheritdoc />
        public Task<IEnumerable<ChargeGroupModel>> FetchChargeGroupAsync(ChargeGroupFilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (!string.IsNullOrEmpty(model.ChargeGroupName))
            {
                where += $@" AND TRIM(UPPER(""ChargeGroupName"")) = '{model.ChargeGroupName.Trim().ToUpper()}'";
            }

            //if (model.DepartmentId > 0)
            //{
            //    where += $@" AND ""DepartmentId"" = {model.DepartmentId}";
            //}
            if (model.ChargeGroupId > 0)
            {
                where += $@" AND cg.""ChargeGroupId"" = {model.ChargeGroupId}";
            }
        

            var query = $@" SELECT COUNT(*) OVER () AS ""TotalItems"" ,* FROM ""ChargeGroup"" cg join ""Department"" d on d.""DepartmentId"" = cg.""DepartmentId""
                            left join ""Charge"" c on c.""ChargeGroupId"" = cg.""ChargeGroupId""
                       { where} Order by cg.""ChargeGroupId"" DESC";

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

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

    }
}