namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Dapper;
    using Domain.Entities.PediatricGraph;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Shared.EntityModels;

    using Hims.Shared.UserModels.PediatricGraphs;

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

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

        /// <inheritdoc/>
        public async Task<int> ModifyPediatricAuthority(PediatricChartAuthorityModel model)
        {
            var checkQuery = $@"select count(*) from ""PediatricChartAuthority"" where lower(""AuthorityName"") = '{model.AuthorityName.ToLower()}' ";
            if (model.PediatricChartAuthorityId > 0)
            {
                checkQuery += $@" and ""PediatricChartAuthorityId"" <> {model.PediatricChartAuthorityId}";
                var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(checkQuery);
                if (checkIf > 0)
                {
                    return -1;
                }

                var oldData = await this.unitOfWork.PediatricChartAuthoritys.FindAsync(x => x.PediatricChartAuthorityId == model.PediatricChartAuthorityId);
                if (oldData == null) { return 0; }

                oldData.AuthorityName = model.AuthorityName;
                oldData.ModifiedBy = model.CreatedBy;
                oldData.ModifiedDate = DateTime.Now;

                return await this.unitOfWork.PediatricChartAuthoritys.UpdateAsync(oldData);
            }

            var check = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(checkQuery);
            if (check > 0)
            {
                return -1;
            }

            var iModel = new PediatricChartAuthority
            {
                Active = true,
                AuthorityName = model.AuthorityName,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now
            };

            return await this.unitOfWork.PediatricChartAuthoritys.InsertAsync(iModel);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<PediatricChartAuthorityModel>> FetchAuthorityAsync(PediatricChartAuthorityModel model)
        {
            var where = "where 1=1";
            var query = $@"select pc.""PediatricChartAuthorityId"",pc.""AuthorityName"",pc.""CreatedBy"" ,pc.""CreatedDate"" ,	pc.""ModifiedBy"",pc.""ModifiedDate"",pc.""Active"",
		                        c.""FullName"" as ""CreatedByName"", m.""FullName"" as ""ModifiedByName""
	                        from ""PediatricChartAuthority"" pc
	                        left join ""Account"" c on c.""AccountId"" = pc.""CreatedBy""
	                        left join ""Account"" m on m.""AccountId"" = pc.""ModifiedBy""
                            {where}
	                        order by pc.""CreatedDate"" desc ";

            return await this.unitOfWork.Current.QueryAsync<PediatricChartAuthorityModel>(query);
        }

        /// <inheritdoc/>
        public async Task<int> ChangeAuthorityStatusAsync(PediatricChartAuthorityModel model)
        {
            var query = $@"update ""PediatricChartAuthority"" set ""Active"" = '{model.Active}' where ""PediatricChartAuthorityId"" = {model.PediatricChartAuthorityId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<PediatricChartTypeModel>> FetchPediatricChartType()
        {
            var query = $@"select * from ""PediatricChartType"" order by 1 desc ";
            return await this.unitOfWork.Current.QueryAsync<PediatricChartTypeModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<PediatricBaseDisplayModel>> FetchPediatricDisplayAsync()
        {
            var query = $@"select pct.""TypeName"" , pct.""PediatricChartTypeId"", pca.""AuthorityName"" , pca.""PediatricChartAuthorityId"" 
	                            from ""PediatricChartType"" pct
	                            cross join ""PediatricChartAuthority"" pca 
	                            order by  (pca.""AuthorityName"", pct.""TypeName"") asc";
            return await this.unitOfWork.Current.QueryAsync<PediatricBaseDisplayModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<PediatricAgeWiseDataModel>> FetchAgeWiseDataAsync(PediatricAgeWiseDataModel model)
        {
            var where = "where 1=1 ";
            if(model.PediatricChartTypeId != null && model.PediatricChartTypeId > 0)
            {
                where += $@" and pd.""PediatricChartTypeId"" = {model.PediatricChartTypeId}";
            } 

            if(model.PediatricChartAuthorityId != null && model.PediatricChartAuthorityId > 0)
            {
                where += $@" and pd.""PediatricChartAuthorityId"" = {model.PediatricChartAuthorityId}";
            }

            var query = $@"SELECT pca.""AuthorityName"" , pct.""TypeName"" ,pd.""PediatricAgeWiseDataId"", pd.""PediatricChartAuthorityId"", pd.""PediatricChartTypeId"", pd.""Gender"", pd.""AgeInMonth"", pd.""CreatedBy"", pd.""CreatedDate"", pd.""ModifiedBy"", pd.""ModifiedDate"", pd.""Active"",
                                pd.""L"",pd.""M"",pd.""SD"",pd.""P01"",pd.""P1"",pd.""P3"",pd.""P5"",pd.""P10"",pd.""P15"",pd.""P25"",pd.""P50"",pd.""P75"",pd.""P85"",pd.""P90"",pd.""P95"",pd.""P97"",pd.""P99"",pd.""P999""
	                            FROM ""PediatricAgeWiseData"" pd
	                            join ""PediatricChartAuthority"" pca on pca.""PediatricChartAuthorityId"" = pd.""PediatricChartAuthorityId"" 
	                            join ""PediatricChartType"" pct on pct.""PediatricChartTypeId"" = pd.""PediatricChartTypeId"" 
	                            {where}  
	                            order by pd.""AgeInMonth"" asc";

            return await this.unitOfWork.Current.QueryAsync<PediatricAgeWiseDataModel>(query);
        }


        /// <inheritdoc/>
        public async Task<IEnumerable<PediatricAgeWiseDataZScoreModel>> FetchAgeWiseDataZScoreAsync(PediatricAgeWiseDataZScoreModel model)
        {
            var where = "where 1=1 ";
            if (model.PediatricChartTypeId != null && model.PediatricChartTypeId > 0)
            {
                where += $@" and pd.""PediatricChartTypeId"" = {model.PediatricChartTypeId}";
            }

            if (model.PediatricChartAuthorityId != null && model.PediatricChartAuthorityId > 0)
            {
                where += $@" and pd.""PediatricChartAuthorityId"" = {model.PediatricChartAuthorityId}";
            }

            var query = $@"SELECT pca.""AuthorityName"" , pct.""TypeName"" ,pd.""PediatricAgeWiseDataId"", pd.""PediatricChartAuthorityId"", pd.""PediatricChartTypeId"", pd.""Gender"", pd.""AgeInMonth"", pd.""CreatedBy"", pd.""CreatedDate"", pd.""ModifiedBy"", pd.""ModifiedDate"", pd.""Active"",
                              pd.""L"",pd.""M"",pd.""SD"",pd.""S"" ,pd.""Minus3SD"" ,pd.""Minus2SD"" ,pd.""Minus1SD"" ,pd.""Median"" ,pd.""1SD"" as ""OneSD"" ,pd.""2SD"" as ""TwoSD"",pd.""3SD"" as ""ThreeSD""
	                           FROM ""PediatricAgeWiseData"" pd
	                          join ""PediatricChartAuthority"" pca on pca.""PediatricChartAuthorityId"" = pd.""PediatricChartAuthorityId"" 
	                          join ""PediatricChartType"" pct on pct.""PediatricChartTypeId"" = pd.""PediatricChartTypeId"" 
	                          {where}
	                          order by pd.""AgeInMonth"" asc";

            return await this.unitOfWork.Current.QueryAsync<PediatricAgeWiseDataZScoreModel>(query);
        }
    }
}