using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Dapper;
using Hims.Shared.UserModels.ProgressReport.Labs;
using MedicationInfo = Hims.Shared.UserModels.ProgressReport.MedicationInfo;

namespace Hims.Infrastructure.Services
{
    using Hims.Domain.Configurations;
    using Hims.Domain.Repositories.UnitOfWork;
    using Hims.Domain.Services;
    using System.Linq;

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

        /// <summary>
        /// The amazon s3 configuration.
        /// </summary>
        private readonly IAmazonS3Configuration configuration;

        /// <inheritdoc cref="IChatService" />
        public ProgressReportLabService(IUnitOfWork unitOfWork, IAmazonS3Configuration configuration)
        {
            this.unitOfWork = unitOfWork;
            this.configuration = configuration;
        }

        public async Task<IEnumerable<MasterViewModel>> FetchMasterLabsAsync(string term, int locationId)
        {
            var query = $@"SELECT
	                         LH.""LabHeaderId"" ""Id"",
	                        LH.""LabName"" ""Name"",
	                        LH.""LabCode"" ""Code"",
	                        LHM.""InPatientCharge"" ""Cost""
                        FROM
	                        ""LabHeader"" LH
                            JOIN ""LocationLabHeaderMap"" LHM on LHM.""LabHeaderId"" = LH.""LabHeaderId"" 
                            WHERE  LHM.""LocationId""={locationId} AND  (LH.""LabName"" ilike '%{term}%' OR  LH.""LabCode"" ilike '%{term}%')
	                        LIMIT 10";

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

        public async Task<IEnumerable<NewLabsViewModel>> FetchAsync(FilterModel model)
        {
            var whereQuery = model.AdmissionIds != null && model.AdmissionIds.Any()
                ? $@" nlbh.""AdmissionId"" IN ({string.Join(",", model.AdmissionIds.Select(x => x).ToArray())})"
                : $@" nlbh.""AdmissionId"" = {model.AdmissionId}";

            var dateWhere = model.Date != null
                ? $@" AND to_char( nlbh.""CreatedDate"", 'YYYY-MM-DD' )::DATE = '{model.Date:yyyy-MM-dd}'::DATE "
                : string.Empty;

            var query = $@"SELECT
	                            nlbd.""NewLabBookingDetailId"",
	                            nlbd.""NewLabBookingHeaderId"",
	                            lmd.""TestName"",
	                            lmd.""TestCode"",
                                s.""Cost"",
                                s.""Notes"",
	                            nlbd.""LabMainDetailId"",
                                lbs.""Status"",
                                c.""FullName"" ""CreatedByName"",
                                nlbh.""CreatedDate"" as ""Date"",
                                nlbh.""CreatedDate"",
                                pa.""Salutation"",
                                pa.""FullName"",
                                pa.""Age"",
                                pa.""Gender"",
                                pa.""UMRNo"",
                                (CASE WHEN pa.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.configuration.BucketURL}', pa.""Guid"", '/', pa.""ThumbnailUrl"") ELSE NULL END) AS ""PatientImage"" 

                            FROM
	                            ""NewLabBookingDetail"" nlbd
                                JOIN ""NewLabBookingHeader"" nlbh on nlbh.""NewLabBookingHeaderId"" = nlbd.""NewLabBookingHeaderId""
                                JOIN ""Admission"" aa on aa.""AdmissionId"" = nlbh.""AdmissionId""
	                            JOIN ""Patient"" pa on pa.""PatientId"" = aa.""PatientId""
                                JOIN ""LabMainDetail"" lmd ON lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
                                join ""LabServices"" s on s.""LabServicesId"" = nlbd.""LabServicesId""
                                Join ""LabBookingStatus"" lbs on lbs.""LabBookingStatusId"" = nlbd.""LabBookingStatusId""
                                JOIN ""Account"" c on c.""AccountId"" = nlbh.""CreatedBy""
                            WHERE
	                            {whereQuery} {dateWhere}";

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

        public async Task<IEnumerable<MedicationInfo.LabFetchModel>> FetchLabInfoAsync(FilterModel model)
        {
            var dateWhere = model.Date != null
                ? $@" AND to_char(COALESCE(LBH.""LabDate"", h.""CreatedDate""), 'YYYY-MM-DD' )::DATE = '{model.Date:yyyy-MM-dd}'::DATE "
                : string.Empty;

            var query = $@"SELECT
	                            h.""AdmissionId"",
	                            COUNT(*) OVER() AS ""Count""
                            FROM
	                            ""LabBookingDetail"" LBH
                                JOIN ""LabBookingHeader"" h on h.""LabBookingHeaderId"" = LBH.""LabBookingHeaderId""
                                JOIN ""LabHeader"" LH ON LH.""LabHeaderId"" = LBH.""LabHeaderId""
                            WHERE
	                            h.""AdmissionId"" IN ({string.Join(",", model.AdmissionIds.Select(x => x).ToArray())}) {dateWhere}";

            var records = await this.unitOfWork.Current.QueryAsync<MedicationInfo.LabFetchModel>(query);
            return records;
        }
    }
}
