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

        /// <inheritdoc cref="IChargeTypesService" />
        public ChargeTypesService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

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

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

            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", * FROM ""ChargeTypes"" {where} Order by ""ChargeTypesId"" DESC";

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

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

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

                var chargeTypes = new ChargeTypes
                {
                    Active = true,    
                    ChargeName = model.ChargeName,
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.Now,
                };

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

            return 0;
        }       

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

            var chargeTypes = await this.unitOfWork.ChargeTypes.FindAsync(m => m.ChargeTypesId == model.ChargeTypesId);
            chargeTypes.ChargeName = model.ChargeName;
            chargeTypes.Active = true;
            chargeTypes.ModifiedBy = model.ModifiedBy;
            chargeTypes.ModifiedDate = DateTime.Now;
            return await this.unitOfWork.ChargeTypes.UpdateAsync(chargeTypes);
        }

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

        public async Task<string> FindNameByChargeId(int? chargeTypesId)
        {
            var query = $@"SELECT ""ChargeName"" FROM ""ChargeTypes"" WHERE ""ChargeTypesId"" = {chargeTypesId}";
            var response = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>(query);
            return response;
        }


        /// <inheritdoc />
        public async Task<int> ModifyStatusAsync(ChargeTypesModel model)
        {
            var query = $@"UPDATE ""ChargeTypes""
	                           SET ""ModifiedBy""={model.CreatedBy}, ""ModifiedDate""=now(), ""Active""= {model.Active}
	                           WHERE ""ChargeTypesId""= {model.ChargeTypesId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

    }
}