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 Hims.Shared.UserModels.Laboratory;

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

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

        /// <inheritdoc/>
        public async Task<IEnumerable<LabsDashboardRevenueModel>> FetchLabRevenueGraphReport(LabsDashboardModel model)
        {
            var where = $@"where 1=1";
            if (model.FromDate != null)
            {
                where += $@"and LBH.""CreatedDate""::date >= '{model.FromDate}'::Date";
            }
            if (model.LocationId != null)
            {
                where += $@"and LBH.""LocationId"" =  {model.LocationId} ";
            }

            if (model.ToDate != null)
            {
                where += $@"and LBH.""CreatedDate""::date <= '{model.ToDate}'::Date";
            }

            //var query = $@"select  distinct A.""LabName""::text,round(A.""LabTotal"" / A.""GrandTotal"" * 100, 2)::text ""LabTotalPercentage"" from ( 
            //    SELECT LH.""LabName"",LBD.""Amount"",LBD.""NetAmount"",sum(LBD.""NetAmount"") over(partition by LBH.""LabBookingHeaderId"") as""LabTotal"",
            //    sum(LBD.""NetAmount"") over() as""GrandTotal"",
            //    LBH.""LabBookingHeaderId"",
            // sum(LBD.""NetAmount"") over() as""OverallNetAmount"",
            //    sum(LBD.""DiscountAmount"") over() as""OverallDiscountAmount""
            //    FROM""LabBookingHeader"" LBH
            //    join""LabBookingDetail"" LBD on LBD.""LabBookingHeaderId"" = LBH.""LabBookingHeaderId""
            //    join""LabHeader"" LH on LH.""LabHeaderId"" = LBD.""LabHeaderId""
            //    join""Patient"" P on P.""PatientId"" = LBH.""PatientId""
            //    join""Account"" A on A.""AccountId"" = LBH.""CreatedBy"" 
            //    {where}) a order by ""LabTotalPercentage"" desc";
            var query = $@"select * from (select A.""GrandTotal"",A.""LabTotal"",A.""LabName"",A.""LabTotalPercentage"",row_number()over(partition by split_part(""LabTotalPercentage""::text,'.',1)::int order by ""LabTotalPercentage"" desc ) ""Row"" from (select  distinct  A.""GrandTotal"",A.""LabTotal"",A.""LabName"", round(A.""LabTotal"" / A.""GrandTotal"" * 100, 2)::text::numeric ""LabTotalPercentage"" from ( 
                SELECT LH.""LabName"",LBD.""Amount"",LBD.""NetAmount"",
	            sum(LBD.""NetAmount"") over(partition by LH.""LabHeaderId"") as""LabTotal"",
                sum(LBD.""NetAmount"") over() as""GrandTotal"",
                LBH.""LabBookingHeaderId"",
	            sum(LBD.""NetAmount"") over() as""OverallNetAmount"",
                sum(LBD.""DiscountAmount"") over() as""OverallDiscountAmount""
                FROM ""LabBookingHeader"" LBH
                join ""LabBookingDetail"" LBD on LBD.""LabBookingHeaderId"" = LBH.""LabBookingHeaderId""
                join ""LabHeader"" LH on LH.""LabHeaderId"" = LBD.""LabHeaderId""
                join ""Patient"" P on P.""PatientId"" = LBH.""PatientId""
                join ""Account"" A on A.""AccountId"" = LBH.""CreatedBy""
                where 1 = 1 and LBH.""LocationId"" =  {model.LocationId} ) a order by ""LabTotalPercentage"" desc ) a ) a order by 2 desc limit 10";
            return await this.unitOfWork.Current.QueryAsync<LabsDashboardRevenueModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabHeaderModel>> FetchLabs()
        {
            var query = $@"Select string_to_array(lh.""LabName""||','||ld.""TestParameter"",',') as ""LabData"" from ""LabHeader"" lh join ""LabDetail"" ld on lh.""LabHeaderId"" = ld.""LabHeaderId"" ";
            return await this.unitOfWork.Current.QueryAsync<LabHeaderModel>(query);
        }
    }
}