using Dapper;

namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Hims.Domain.Entities;
    using Hims.Domain.Repositories.UnitOfWork;
    using Hims.Domain.Services;
    using Hims.Shared.EntityModels;
    using Hims.Shared.UserModels.MasterBill;
    using Hims.Shared.UserModels.Slots;
    using Resource = Hims.Shared.UserModels.Discharge.Resource;

    /// <summary> The chat service.</summary>
    public class MasterBillService : IMasterBillService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc cref="IChatService" />
        public MasterBillService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;


        //public async Task<int> InsertAsync(InsertModel model)
        //{
        //    var record = new MasterBill
        //    {
        //        ModulesMasterId = (int)model.ModulesMasterId,
        //        Total = model.Total,
        //        BillDate = model.BillDate,
        //        BillStatusTypeId = model.BillStatusTypeId,
        //        BillNumber = model.BillNumber,
        //        CreatedBy = model.CreatedBy,
        //        CreatedDate = model.CreatedDate,
        //        PatientId = (int)model.PatientId,
        //        LocationId =(int) model.LocationId
        //    };

        //    var response = await this.unitOfWork.MasterBill.InsertAsync(record);
        //    return response;
        //}

        //public async Task<int> UpdateAsync(InsertModel model)
        //{
        //    var record = await this.unitOfWork.MasterBill.FindAsync(x => x.MasterBillId == model.MasterBillId);

        //    record.ModulesMasterId = (int)model.ModulesMasterId;
        //    record.Total = model.Total;
        //    record.BillDate = model.BillDate;
        //    record.BillStatusTypeId = model.BillStatusTypeId;
        //    record.BillNumber = model.BillNumber;
        //    record.ModifiedBy = model.ModifiedBy;
        //    record.ModifiedDate = model.ModifiedDate;

        //    var response = await this.unitOfWork.MasterBill.UpdateAsync(record);
        //    return response;
        //}

        public async Task<IEnumerable<InsertModel>> FetchAsync(InsertModel model)
        {
            var where = " where 1=1";
            where += $@" and MB.""CreatedDate""::date <= current_date and MB.""BillStatusTypeId""=2 and MB.""ReceiptAreaTypeId""!=3 and MB.""Active"" is true";
            if (model.PatientId > 0)
            {
                where += $@" and P.""PatientId""={model.PatientId}";
            }
            if (model.ReceiptAreaTypeId > 0)
            {
                where += $@" and RA.""ReceiptAreaTypeId""={model.ReceiptAreaTypeId}";
            }
            if (model.LocationId > 0)
            {
                where += $@" and MB.""LocationId""={model.LocationId}";
            }

            var query = $@"select *,
                                        case 
                                        when s.""LogId"" is null then 'PL' 
                                        when s.""LogId""='WS' then 'WS' 
                                        else 'S' end as ""PaymentRoute"", 
                                        case 
                                        when s.""LogId"" is null or s.""LogId""='WS' then null 
                                        else s.""LogId"" end as ""PaymentInitiationLogId""
                                        from (
                                        select MB.""ModuleId"",
                                        MB.""MasterBillId"",
                                        MB.""Total"",
                                        MB.""NetTotal"" ""OverAllTotal"",
                                        MB.""Tax"",
                                        MB.""Discount"",
                                        MB.""ReceiptAreaTypeId"",
                                        MB.""CreatedDate"",
                                        MB.""BillDate"",
                                        MB.""BillNumber"",
                                        MB.""PatientId"",
                                        P.""UMRNo"",
                                        P.""FullName"" as ""PatientName"",
                                        RA.""Name"",
                                        SUM(COALESCE(R.""Cost"",0))-SUM(COALESCE(RC.""Cost"",0)) ""PaidAmount"",
                                        COALESCE(MB.""RemovedAmount"",0) ""RemovedAmount"",
                                        COALESCE(MB.""NetTotal"",0)-COALESCE(MB.""RemovedAmount"",0) ""NetTotal""
                                        from ""MasterBill"" MB
                                        left join ""ReceiptAreaType"" RA on RA.""ReceiptAreaTypeId"" =MB.""ReceiptAreaTypeId""
                                        left join ""Receipt"" R on R.""MasterBillId""=MB.""MasterBillId"" and R.""ReceiptTypeId""=1
                                        left join ""Receipt"" RC on RC.""MasterBillId""=MB.""MasterBillId"" and RC.""ReceiptTypeId""=2
                                        left join ""Patient"" P on P.""PatientId""=MB.""PatientId""                                    
                                        {where}
                                        group by
                                        MB.""MasterBillId"",
                                        MB.""Total"",
                                        MB.""NetTotal"",
                                        MB.""Tax"",
                                        MB.""Discount"",
                                        MB.""ModuleId"",
                                        MB.""ReceiptAreaTypeId"",
                                        MB.""CreatedDate"",
                                        MB.""BillDate"",
                                        MB.""BillNumber"",
                                        MB.""PatientId"",
                                        P.""UMRNo"",
                                        P.""FullName"",
                                        RA.""Name""
                                        order by MB.""MasterBillId"" desc	
                                        )
                                        A
                                       left JOIN LATERAL (
                                         SELECT 
	                                        (case when AT.""Transaction"" is not null and AT.""Transaction""<>'' then ( AT.""Transaction""::json->'custom')::TEXT else 'WS'::text END)::text as ""LogId"",		
	                                        AT.""AppointmentTransactionId"" 
                                         FROM ""AppointmentTransaction"" AT
                                         WHERE (AT.""AppointmentId""=A.""ModuleId"" and AT.""ReceiptAreaTypeId""=A.""ReceiptAreaTypeId"" and AT.""PatientId""=A.""PatientId"") 
	                                        limit 1
                                        ) s on true where  A.""PaidAmount"" < A.""NetTotal""";

            var record = await this.unitOfWork.Current.QueryAsync<InsertModel>(query);
            return record;
        }

        public async Task<IEnumerable<InsertModel>> FetchPackagesAsync(InsertModel model)
        {
            var query = $@"select * from (
                            select F.""TotalAmount"" as ""Total"",F.""DiscountDetails"" as ""Discount"",F.""FinalAmount"" as ""NetTotal"",(A1.""Paid""-A2.""Refunded"") as ""PaidAmount"",(F.""TotalAmount""-(A1.""Paid""-A2.""Refunded"")) as ""PendingAmount"",F.""Active"" from ""FinalBill"" F
                            join ""Appointment"" A on A.""AppointmentId""= F.""AppointmentId""
                            left join lateral (
                            select COALESCE(sum(R.""Cost""),0) as ""Paid"" from ""Receipt"" R
    
                            where R.""ReceiptTypeId""=1 and R.""AppointmentId""=F.""AppointmentId"" limit 1
                            )
                            A1 on true
                            left join lateral (
                            select COALESCE(sum(R.""Cost""),0) as ""Refunded"" from ""Receipt"" R    
                                where R.""ReceiptTypeId""=2 and R.""AppointmentId""=F.""AppointmentId"" limit 1
                            )
                            A2 on true
                            )A where A.""PendingAmount"">0 and A.""Active"" is true";

            var record = await this.unitOfWork.Current.QueryAsync<InsertModel>(query);
            return record;
        }
        public async Task<IEnumerable<FetchModel>> FetchExcelAsync(FilterModel model)
        {
            //var where = " where 1=1";
            //if (model.PatientId > 0)
            //{
            //    where += $@"and P.""PatientId""={model.PatientId}";
            //}
            //if (model.ModulesMasterId > 0)
            //{
            //    where += $@"and MM.""ReceiptAreaTypeId""={model.ReceiptAreaTypeId}";
            //}
            var paramsString = "";

            paramsString += model.FromDate != null ? $@"'{model.FromDate}'::timestamp without time zone" : $@" null";
            paramsString += model.ToDate != null ? $@", '{model.ToDate}'::timestamp without time zone" : $@", null";
            paramsString += model.LocationId > 0 ? $@", '{model.LocationId}'" : $@", null";
            paramsString += model.ReceiptAreaTypeId > 0 ? $@", '{model.ReceiptAreaTypeId}'" : $@", null";
            paramsString += model.PatientId > 0 ? $@", '{model.PatientId}'" : $@", null";
            paramsString += model.ServiceFromDate != null ? $@", '{model.ServiceFromDate}'::date" : $@" null";
            paramsString += model.ServiceToDate != null ? $@", '{model.ServiceFromDate}'::date" : $@", null";

            var query = $@"Select * from ""udf_report_Finance_Billwise""({paramsString})";// servicedate 
                                                                                          //var query = $@"Select * from ""Masterbills_AppointmentReports""({paramsString})";


            var record = await this.unitOfWork.Current.QueryAsync<FetchModel>(query);
            return record;
        }

        public Task<IEnumerable<FetchModel>> FetchPatientDueAsync(FilterModel model)
        {
            var where = $@"where 1=1 and mb.""BillStatusTypeId"" = 2 and mb.""ReceiptAreaTypeId""!=3 and MB.""Active"" is true";
            if (model.PatientId != null)
            {
                where += $@" and mb.""PatientId""={model.PatientId}";
            }
            if (model.LocationId != null)
            {
                where += $@" and mb.""LocationId"" = {model.LocationId}";
            }
            var query = $@"select *,
                                        case 
                                        when s.""LogId"" is null then 'PL' 
                                        when s.""LogId""='WS' then 'WS' 
                                        else 'S' end as ""PaymentRoute"", 
                                        case 
                                        when s.""LogId"" is null or s.""LogId""='WS' then null 
                                        else s.""LogId"" end as ""PaymentInitiationLogId""
                                        from (
                                        select MB.""ModuleId"",
                                        MB.""MasterBillId"",
                                        MB.""Total"",
                                        MB.""NetTotal"" ""OverAllTotal"",
                                        MB.""Tax"",
                                        MB.""Discount"",
                                        MB.""ReceiptAreaTypeId"",
                                        MB.""CreatedDate"",
                                        MB.""BillDate"",
                                        MB.""BillNumber"",
                                        MB.""PatientId"",
                                        P.""FullName"" as ""PatientName"",
                                        RA.""Name"" ""ModulesName"",
                                        SUM(COALESCE(R.""Cost"",0))-SUM(COALESCE(RC.""Cost"",0)) ""PaidAmount"",
                                        COALESCE(MB.""RemovedAmount"",0) ""RemovedAmount"",
                                        COALESCE(MB.""NetTotal"",0)-COALESCE(MB.""RemovedAmount"",0) ""NetTotal""
                                        from ""MasterBill"" MB
                                        left join ""ReceiptAreaType"" RA on RA.""ReceiptAreaTypeId"" =MB.""ReceiptAreaTypeId""
                                        left join ""Receipt"" R on R.""MasterBillId""=MB.""MasterBillId"" and R.""ReceiptTypeId""=1
                                        left join ""Receipt"" RC on RC.""MasterBillId""=MB.""MasterBillId"" and RC.""ReceiptTypeId""=2
                                        left join ""Patient"" P on P.""PatientId""=MB.""PatientId""                                    
                                        {where}
                                        group by
                                        MB.""MasterBillId"",
                                        MB.""Total"",
                                        MB.""NetTotal"",
                                        MB.""Tax"",
                                        MB.""Discount"",
                                        MB.""ModuleId"",
                                        MB.""ReceiptAreaTypeId"",
                                        MB.""CreatedDate"",
                                        MB.""BillDate"",
                                        MB.""BillNumber"",
                                        MB.""PatientId"",
                                        P.""FullName"",
                                        RA.""Name""
                                        order by MB.""MasterBillId"" desc	
                                        )
                                        A
                                        left JOIN LATERAL (
                                         SELECT 
	                                        (case when AT.""Transaction"" is not null and AT.""Transaction""<>'' then ( AT.""Transaction""::json->'custom')::TEXT else 'WS'::text END)::text as ""LogId"",		
	                                        AT.""AppointmentTransactionId"" 
                                         FROM ""AppointmentTransaction"" AT
                                         WHERE (AT.""AppointmentId""=A.""ModuleId"" and AT.""ReceiptAreaTypeId""=A.""ReceiptAreaTypeId"") 
	                                        limit 1
                                        ) s on true where  A.""PaidAmount"" < A.""NetTotal""";
            //var query = $@"select mb.""MasterBillId"",mb.""ModuleId"",mb.""BillNumber"",mb.""BillStatusTypeId"",mb.""PatientId"",mb.""LocationId"",mb.""ReceiptAreaTypeId"" from ""MasterBill"" mb {where}";
            return this.unitOfWork.Current.QueryAsync<FetchModel>(query);
        }
    }
}
