namespace Hims.Infrastructure.Services
{
    using Dapper;
    using Domain.Configurations;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Hims.Domain.Entities;
    using Hims.Shared.EntityModels;
    using Hims.Shared.Library;
    using Hims.Shared.Library.Enums;
    using Hims.Shared.Library.Helpers;
    using Hims.Shared.UserModels;
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;

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

        /// <summary>
        /// The timeline service.
        /// </summary>
        private readonly ITimelineService timelineService;

        /// <inheritdoc cref="IEmergencyEncounterService"/>
        public EmergencyEncounterServices(ITimelineService timelineService, IUnitOfWork unitOfWork)
        {
            this.unitOfWork = unitOfWork;
            this.timelineService = timelineService;
        }

        public async Task<CommonResponse> AddAsync(EmergencyEncounterModifyModel model)
        {

            var commonResponse = new CommonResponse { Status = 1 };
            var checkIf = model.IsAdmission
                ? await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""EmergencyEncounterId"") FROM ""EmergencyEncounter"" WHERE ""AdmissionId"" = {model.AppointmentId}")
                : await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""EmergencyEncounterId"") FROM ""EmergencyEncounter"" WHERE ""AppointmentId"" = {model.AppointmentId}");
            if (checkIf > 0)
            {
                commonResponse.Response = -1;
                return commonResponse;
            }
            var values = this.unitOfWork.Appointments.Find(s => s.AppointmentId == model.AppointmentId);
            var encounter = new EmergencyEncounter
            {
                Active = true,
                AppointmentId = model.AppointmentId,
                CreatedBy = (int)model.ModifiedBy,
                CreatedDate = DateTime.UtcNow,
                PatientId = values.PatientId,
            };

            switch (model.Type)
            {
                case EmergencyEncounterType.EmergencyTriage:
                    encounter.EmergencyTriage = model.JsonString;
                    break;
                case EmergencyEncounterType.NursingERForm:
                    encounter.NursingERForm = model.JsonString;
                    break;

            }

            try
            {
                var response = await this.unitOfWork.EmergencyEncounter.InsertAsync(encounter);
                commonResponse.Response = response;
                return commonResponse;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public Task<EmergencyEncounterModel> FindAsync(int appointmentId, bool isAdmission)
        {
            var query = isAdmission ? $@"SELECT A.""AdmissionId"" as ""AppointmentId"",e.""EmergencyEncounterId"",e.""EmergencyTriage"",e.""NursingERForm"",e.""Active"",e.""PatientId"" from ""Admission""a
                                left join ""EmergencyEncounter"" e on e.""AdmissionId""=a.""AdmissionId""
                            where A.""AdmissionId""='{appointmentId}' and A.""Active"" Is true"
                                 : $@"select a.""AppointmentId"",e.""EmergencyEncounterId"",e.""EmergencyTriage"",e.""NursingERForm"",e.""Active"",e.""PatientId"" from ""Appointment""a
                                     left join ""EmergencyEncounter"" e on e.""AppointmentId""=a.""AppointmentId""
                                where A.""AppointmentId""='{appointmentId}' and A.""Active"" Is true";
            return this.unitOfWork.Current.QueryFirstOrDefaultAsync<EmergencyEncounterModel>(query);
        }

        public Task<IEnumerable<EmergencyEncounterModel>> FindAllAsync(int ProviderId)
        {
            var where = @" WHERE 1=1 ";
            if (ProviderId != 0)
            {
                where += $@" AND A.""ProviderId"" ={ProviderId}";
            }
           
            //var query =  $@"select * from ""EmergencyEncounter""";
            //var qry = $@"select EE.* from ""EmergencyEncounter"" EE join ""Appointment"" A on A.""AppointmentId""=EE.""AppointmentId"" {where}";
            var query = $@" select EE.*,A.""ProviderId"",P.""UMRNo"",  TO_CHAR(A.""AppointmentTime"", 'hh12:mi AM')  as ""AppointmentTime"",P.""FullName"" as ""PatientName""
                    from ""EmergencyEncounter""  EE
            join ""Appointment"" A on A.""AppointmentId""=EE.""AppointmentId""
                join  ""Patient"" P on  P.""PatientId""=A.""PatientId""{where}";

            return this.unitOfWork.Current.QueryAsync<EmergencyEncounterModel>(query);
        }
        public async Task<EmergencyEncounterResource> FindDashboardAsync(int appointmentId, EmergencyEncounterType type, bool isAdmission)
        {
            var emergencyEncounter =
                     await this.unitOfWork.EmergencyEncounter.FindAsync(m => m.AppointmentId == appointmentId);

            var emergencyEncounterResource = new EmergencyEncounterResource
            {
                AppointmentId = appointmentId,
                EmergencyEncounterId = null,
                JsonString = null
            };

            if (emergencyEncounter != null)
            {
                emergencyEncounterResource.EmergencyEncounterId = emergencyEncounter.EmergencyEncounterId;
                switch (type)
                {
                    case EmergencyEncounterType.EmergencyTriage:
                        emergencyEncounterResource.JsonString = emergencyEncounter.EmergencyTriage;
                        break;
                    case EmergencyEncounterType.NursingERForm:
                        emergencyEncounterResource.JsonString = emergencyEncounter.NursingERForm;
                        break;
                }
            }
            return emergencyEncounterResource;
        }

        public async Task<CommonResponse> UpdateAsync(EmergencyEncounterModifyModel model)
        {
            var commonResponse = new CommonResponse { Status = 1 };
            var encounter = await this.unitOfWork.EmergencyEncounter.FindAsync(m => m.EmergencyEncounterId == model.EmergencyEncounterId);

            var checkIf = model.IsAdmission
                    ? await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""EmergencyEncounterId"") FROM ""EmergencyEncounter"" WHERE ""AdmissionId"" = '{model.AppointmentId}' AND ""EmergencyEncounterId"" <> '{model.EmergencyEncounterId}'")
                    : await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""EmergencyEncounterId"") FROM ""EmergencyEncounter"" WHERE ""AppointmentId"" = '{model.AppointmentId}' AND ""EmergencyEncounterId"" <> '{model.EmergencyEncounterId}'");

            if (checkIf > 0)
            {
                commonResponse.Response = -1;
                return commonResponse;
            }

            encounter.ModifiedBy = model.ModifiedBy;
            encounter.ModifiedDate = DateTime.UtcNow;

            switch (model.Type)
            {
                case EmergencyEncounterType.EmergencyTriage:
                    encounter.EmergencyTriage = model.JsonString;
                    break;
                case EmergencyEncounterType.NursingERForm:
                    encounter.NursingERForm = model.JsonString;
                    break;
            }


            var updated = await this.unitOfWork.EmergencyEncounter.UpdateAsync(encounter);


            commonResponse.Response = updated > 0 ? encounter.EmergencyEncounterId : 0;
            return commonResponse;
        }
    }
}
