using System.Linq;

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

        /// <inheritdoc cref="IPayTypeService" />
        public PayCategoryServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public Task<IEnumerable<PayCategoryModel>> FetchAsync(PayCategoryModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (model.PayCategoryId !=null)
            {
                where += $@" and  PC.""PayCategoryId"" = {model.PayCategoryId} ";
            }

            if (model.Active != null)
            {
                where += $@" and  PC.""Active"" = {model.Active} ";
            }
                var query = $@"SELECT count(PC.""PayCategoryId"") over() as TotalItems, PC.*, AC.""FullName"" as ""CreatedByName"",AM.""FullName"" as ""ModifiedByName""
                            FROM ""PayCategory"" PC
                           Left JOIN ""Account"" AC on AC.""AccountId""=PC.""CreatedBy""
                           Left JOIN ""Account"" AM on AM.""AccountId""=PC.""ModifiedBy"" {where}                        
                Order by ""PayCategoryId"" DESC";

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

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

        }


        /// <inheritdoc />
        public async Task<int> ActivateOrDeactivatePayType(PayCategoryModel model)
        {
            var pay = await this.unitOfWork.PayCategorys.FindAsync(m => m.PayCategoryId == model.PayCategoryId);

            pay.Active = (bool)model.Active;
            pay.ModifiedBy = (int)model.ModifiedBy;
            pay.ModifiedDate = DateTime.Now;
            return await this.unitOfWork.PayCategorys.UpdateAsync(pay);
        }

        /// <inheritdoc/>
        public async Task<int> InsertAsync(PayCategoryModel model)
        {
            try
            {
                var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>($@"SELECT COUNT(""PayCategoryId"") FROM ""PayCategory"" WHERE TRIM(UPPER(""PayCategoryName"")) = '{model.PayCategoryName.ToUpper().Trim()}'");
                if (checkIf > 0)
                {
                    return -1;
                }
                var newpaycat = new PayCategory
                {
                    PayCategoryName = model.PayCategoryName,
                    Active = true,
                    CreatedBy = (int)model.CreatedBy,
                    CreatedDate = DateTime.Now
                };
                return await this.unitOfWork.PayCategorys.InsertAsync(newpaycat);
            }
            catch (Exception) { }
            return 0;
        }

        /// <inheritdoc/>
        public async Task<int> UpdateAsync(PayCategoryModel model)
        {
            var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>($@"Select count(*) from ""PayCategory"" where lower(""PayCategoryName"") = '{model.PayCategoryName.ToLower()}' and ""PayCategoryId"" <>{model.PayCategoryId}");

            if (checkIf > 0)
            {
                return -1;
            }
            var res = await this.unitOfWork.PayCategorys.FindAsync(m => m.PayCategoryId == model.PayCategoryId);
            if (res == null)
            {
                return 0;
            }

            res.PayCategoryName = model.PayCategoryName;
            res.ModifiedBy = model.ModifiedBy;
            res.ModifiedDate = DateTime.Now;
            return await this.unitOfWork.PayCategorys.UpdateAsync(res);
        }
    }
}