namespace Hims.Infrastructure.Services
{
    using System;
    using System.Threading.Tasks;

    using Dapper;

    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;

    using Shared.EntityModels;

    using Hims.Domain.Configurations;
    using Hims.Shared.Library;
    using Hims.Shared.Library.Enums;
    using Hims.Shared.Library.Helpers;
    using Hims.Shared.UserModels;

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

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

        /// <inheritdoc cref="IHomeopathyService" />
        public HomeopathyServices(IUnitOfWork unitOfWork, IAmazonS3Configuration amazonS3Configuration)
        {
            this.unitOfWork = unitOfWork;
            this.amazonS3Configuration = amazonS3Configuration;
        }

        /// <inheritdoc />
        public async Task<HomeopathyResource> FetchAsync(int appointmentId, HomeopathyType type)
        {
            var homeopathy = await this.unitOfWork.Homeopathy.FindAsync(m => m.AppointmentId == appointmentId);

            var homeopathyResource = new HomeopathyResource()
            {
                AppointmentId = appointmentId,
                HomeopathyId = null,
                JsonString = null
            };

            if (homeopathy != null)
            {
                homeopathyResource.HomeopathyId = homeopathy.HomeopathyId;
                switch (type)
                {
                    case HomeopathyType.Confidential:
                        homeopathyResource.JsonString = homeopathy.Confidential;
                        break;
                    case HomeopathyType.CCAndOC:
                        homeopathyResource.JsonString = homeopathy.CCAndOC;
                        break;
                    case HomeopathyType.AdditionalComplaints:
                        homeopathyResource.JsonString = homeopathy.AdditionalComplaints;
                        break;
                    case HomeopathyType.PastIllness:
                        homeopathyResource.JsonString = homeopathy.PastIllness;
                        break;
                    case HomeopathyType.FamilyIllness:
                        homeopathyResource.JsonString = homeopathy.FamilyIllness;
                        break;
                    case HomeopathyType.SpouseAndChildren:
                        homeopathyResource.JsonString = homeopathy.SpouseAndChildren;
                        break;
                    case HomeopathyType.PersonalHistory:
                        homeopathyResource.JsonString = homeopathy.PersonalHistory;
                        break;
                    case HomeopathyType.PersonalHabits:
                        homeopathyResource.JsonString = homeopathy.PersonalHabits;
                        break;
                    case HomeopathyType.AppetiteAndThirst:
                        homeopathyResource.JsonString = homeopathy.AppetiteAndThirst;
                        break;
                    case HomeopathyType.BowelMovements:
                        homeopathyResource.JsonString = homeopathy.BowelMovements;
                        break;
                    case HomeopathyType.Urination:
                        homeopathyResource.JsonString = homeopathy.Urination;
                        break;
                    case HomeopathyType.SweatFeverChill:
                        homeopathyResource.JsonString = homeopathy.SweatFeverChill;
                        break;
                    case HomeopathyType.ChestHeartColdCough:
                        homeopathyResource.JsonString = homeopathy.ChestHeartColdCough;
                        break;
                    case HomeopathyType.SexualSphere:
                        homeopathyResource.JsonString = homeopathy.SexualSphere;
                        break;
                    case HomeopathyType.GeneralComplaints:
                        homeopathyResource.JsonString = homeopathy.GeneralComplaints;
                        break;
                    case HomeopathyType.AffectedFactors:
                        homeopathyResource.JsonString = homeopathy.AffectedFactors;
                        break;
                    case HomeopathyType.EmotionalNature:
                        homeopathyResource.JsonString = homeopathy.EmotionalNature;
                        break;
                    case HomeopathyType.SleepAndDreams:
                        homeopathyResource.JsonString = homeopathy.SleepAndDreams;
                        break;
                    case HomeopathyType.Children:
                        homeopathyResource.JsonString = homeopathy.Children;
                        break;
                }
            }

            return homeopathyResource;
        }

        /// <inheritdoc />
        public Task<HomeopathyModel> FindAsync(int appointmentId)
        {
            var query = $@"SELECT A.""AppointmentId"", cat.*, ATS.""Symptoms"" FROM ""Appointment"" A 
                        LEFT JOIN ""Homeopathy"" cat ON cat.""AppointmentId"" = A.""AppointmentId"" 
                        LEFT JOIN ""AppointmentSymptom"" ATS ON  ATS.""AppointmentId"" = A.""AppointmentId"" 
                        WHERE A.""AppointmentId"" = '{appointmentId}' AND A.""Active"" IS TRUE";
            return this.unitOfWork.Current.QueryFirstOrDefaultAsync<HomeopathyModel>(query);
        }

        /// <inheritdoc />
        public async Task<int> AddAsync(HomeopathyEncounterModifyModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>(
                              $@"SELECT COUNT(""HomeopathyId"") FROM ""Homeopathy"" WHERE ""AppointmentId"" = {model.AppointmentId} AND ""HomeopathyId"" <> {model.HomeopathyId}");
            if (checkIf > 0)
            {
                return -1;
            }

            var encounter = new Homeopathy()
            {
                Active = true,
                AppointmentId = model.AppointmentId,
                HomeopathyDate = DateTime.UtcNow,
                CreatedBy = model.ModifiedBy,
                CreatedDate = DateTime.UtcNow
            };

            switch (model.Type)
            {
                case HomeopathyType.Confidential:
                    encounter.Confidential = model.JsonString;
                    break;
                case HomeopathyType.CCAndOC:
                    encounter.CCAndOC = model.JsonString;
                    break;
                case HomeopathyType.AdditionalComplaints:
                    encounter.AdditionalComplaints = model.JsonString;
                    break;
                case HomeopathyType.PastIllness:
                    encounter.PastIllness = model.JsonString;
                    break;
                case HomeopathyType.FamilyIllness:
                    encounter.FamilyIllness = model.JsonString;
                    break;
                case HomeopathyType.SpouseAndChildren:
                    encounter.SpouseAndChildren = model.JsonString;
                    break;
                case HomeopathyType.PersonalHistory:
                    encounter.PersonalHistory = model.JsonString;
                    break;
                case HomeopathyType.PersonalHabits:
                    encounter.PersonalHabits = model.JsonString;
                    break;
                case HomeopathyType.AppetiteAndThirst:
                    encounter.AppetiteAndThirst = model.JsonString;
                    break;
                case HomeopathyType.BowelMovements:
                    encounter.BowelMovements = model.JsonString;
                    break;
                case HomeopathyType.Urination:
                    encounter.Urination = model.JsonString;
                    break;
                case HomeopathyType.SweatFeverChill:
                    encounter.SweatFeverChill = model.JsonString;
                    break;
                case HomeopathyType.ChestHeartColdCough:
                    encounter.ChestHeartColdCough = model.JsonString;
                    break;
                case HomeopathyType.SexualSphere:
                    encounter.SexualSphere = model.JsonString;
                    break;
                case HomeopathyType.GeneralComplaints:
                    encounter.GeneralComplaints = model.JsonString;
                    break;
                case HomeopathyType.AffectedFactors:
                    encounter.AffectedFactors = model.JsonString;
                    break;
                case HomeopathyType.EmotionalNature:
                    encounter.EmotionalNature = model.JsonString;
                    break;
                case HomeopathyType.SleepAndDreams:
                    encounter.SleepAndDreams = model.JsonString;
                    break;
                case HomeopathyType.Children:
                    encounter.Children = model.JsonString;
                    break;
            }

            return await this.unitOfWork.Homeopathy.InsertAsync(encounter);
        }
        
        /// <inheritdoc />
        public async Task<CommonResponse> AddAltAsync(HomeopathyEncounterModifyModel model)
        {
            var response = new CommonResponse { Status = 1 };
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>(
                              $@"SELECT COUNT(""HomeopathyId"") FROM ""Homeopathy"" WHERE ""AppointmentId"" = {model.AppointmentId} AND ""HomeopathyId"" <> {model.HomeopathyId}");
            if (checkIf > 0)
            {
                response.Response = -1;
                return response;
            }

            var encounter = new Homeopathy()
            {
                Active = true,
                AppointmentId = model.AppointmentId,
                HomeopathyDate = DateTime.UtcNow,
                CreatedBy = model.ModifiedBy,
                CreatedDate = DateTime.UtcNow
            };

            switch (model.Type)
            {
                case HomeopathyType.Confidential:
                    encounter.Confidential = model.JsonString;
                    break;
                case HomeopathyType.CCAndOC:
                    encounter.CCAndOC = model.JsonString;
                    break;
                case HomeopathyType.AdditionalComplaints:
                    encounter.AdditionalComplaints = model.JsonString;
                    break;
                case HomeopathyType.PastIllness:
                    encounter.PastIllness = model.JsonString;
                    break;
                case HomeopathyType.FamilyIllness:
                    encounter.FamilyIllness = model.JsonString;
                    break;
                case HomeopathyType.SpouseAndChildren:
                    encounter.SpouseAndChildren = model.JsonString;
                    break;
                case HomeopathyType.PersonalHistory:
                    encounter.PersonalHistory = model.JsonString;
                    break;
                case HomeopathyType.PersonalHabits:
                    encounter.PersonalHabits = model.JsonString;
                    break;
                case HomeopathyType.AppetiteAndThirst:
                    encounter.AppetiteAndThirst = model.JsonString;
                    break;
                case HomeopathyType.BowelMovements:
                    encounter.BowelMovements = model.JsonString;
                    break;
                case HomeopathyType.Urination:
                    encounter.Urination = model.JsonString;
                    break;
                case HomeopathyType.SweatFeverChill:
                    encounter.SweatFeverChill = model.JsonString;
                    break;
                case HomeopathyType.ChestHeartColdCough:
                    encounter.ChestHeartColdCough = model.JsonString;
                    break;
                case HomeopathyType.SexualSphere:
                    encounter.SexualSphere = model.JsonString;
                    break;
                case HomeopathyType.GeneralComplaints:
                    encounter.GeneralComplaints = model.JsonString;
                    break;
                case HomeopathyType.AffectedFactors:
                    encounter.AffectedFactors = model.JsonString;
                    break;
                case HomeopathyType.EmotionalNature:
                    encounter.EmotionalNature = model.JsonString;
                    break;
                case HomeopathyType.SleepAndDreams:
                    encounter.SleepAndDreams = model.JsonString;
                    break;
                case HomeopathyType.Children:
                    encounter.Children = model.JsonString;
                    break;
            }

            response.Response = await this.unitOfWork.Homeopathy.InsertAsync(encounter);
            return response;
        }

        /// <inheritdoc />
        public async Task<int> UpdateAsync(HomeopathyEncounterModifyModel model)
        {
            var homeopathy = await this.unitOfWork.Homeopathy.FindAsync(m => m.HomeopathyId == model.HomeopathyId);
            homeopathy.ModifiedBy = model.ModifiedBy;
            homeopathy.ModifiedDate = DateTime.UtcNow;

            switch (model.Type)
            {
                case HomeopathyType.Confidential:
                    homeopathy.Confidential = model.JsonString;
                    break;
                case HomeopathyType.CCAndOC:
                    homeopathy.CCAndOC = model.JsonString;
                    break;
                case HomeopathyType.AdditionalComplaints:
                    homeopathy.AdditionalComplaints = model.JsonString;
                    break;
                case HomeopathyType.PastIllness:
                    homeopathy.PastIllness = model.JsonString;
                    break;
                case HomeopathyType.FamilyIllness:
                    homeopathy.FamilyIllness = model.JsonString;
                    break;
                case HomeopathyType.SpouseAndChildren:
                    homeopathy.SpouseAndChildren = model.JsonString;
                    break;
                case HomeopathyType.PersonalHistory:
                    homeopathy.PersonalHistory = model.JsonString;
                    break;
                case HomeopathyType.PersonalHabits:
                    homeopathy.PersonalHabits = model.JsonString;
                    break;
                case HomeopathyType.AppetiteAndThirst:
                    homeopathy.AppetiteAndThirst = model.JsonString;
                    break;
                case HomeopathyType.BowelMovements:
                    homeopathy.BowelMovements = model.JsonString;
                    break;
                case HomeopathyType.Urination:
                    homeopathy.Urination = model.JsonString;
                    break;
                case HomeopathyType.SweatFeverChill:
                    homeopathy.SweatFeverChill = model.JsonString;
                    break;
                case HomeopathyType.ChestHeartColdCough:
                    homeopathy.ChestHeartColdCough = model.JsonString;
                    break;
                case HomeopathyType.SexualSphere:
                    homeopathy.SexualSphere = model.JsonString;
                    break;
                case HomeopathyType.GeneralComplaints:
                    homeopathy.GeneralComplaints = model.JsonString;
                    break;
                case HomeopathyType.AffectedFactors:
                    homeopathy.AffectedFactors = model.JsonString;
                    break;
                case HomeopathyType.EmotionalNature:
                    homeopathy.EmotionalNature = model.JsonString;
                    break;
                case HomeopathyType.SleepAndDreams:
                    homeopathy.SleepAndDreams = model.JsonString;
                    break;
                case HomeopathyType.Children:
                    homeopathy.Children = model.JsonString;
                    break;
            }

            var updated = await this.unitOfWork.Homeopathy.UpdateAsync(homeopathy);
            return updated > 0 ? homeopathy.HomeopathyId : 0;
        }

        /// <inheritdoc />
        public async Task<CommonResponse> UpdateAltAsync(HomeopathyEncounterModifyModel model)
        {
            var response = new CommonResponse { Status = 1 };
            var homeopathy = await this.unitOfWork.Homeopathy.FindAsync(m => m.HomeopathyId == model.HomeopathyId);
            homeopathy.ModifiedBy = model.ModifiedBy;
            homeopathy.ModifiedDate = DateTime.UtcNow;

            switch (model.Type)
            {
                case HomeopathyType.Confidential:
                    homeopathy.Confidential = model.JsonString;
                    break;
                case HomeopathyType.CCAndOC:
                    homeopathy.CCAndOC = model.JsonString;
                    break;
                case HomeopathyType.AdditionalComplaints:
                    homeopathy.AdditionalComplaints = model.JsonString;
                    break;
                case HomeopathyType.PastIllness:
                    homeopathy.PastIllness = model.JsonString;
                    break;
                case HomeopathyType.FamilyIllness:
                    homeopathy.FamilyIllness = model.JsonString;
                    break;
                case HomeopathyType.SpouseAndChildren:
                    homeopathy.SpouseAndChildren = model.JsonString;
                    break;
                case HomeopathyType.PersonalHistory:
                    homeopathy.PersonalHistory = model.JsonString;
                    break;
                case HomeopathyType.PersonalHabits:
                    homeopathy.PersonalHabits = model.JsonString;
                    break;
                case HomeopathyType.AppetiteAndThirst:
                    homeopathy.AppetiteAndThirst = model.JsonString;
                    break;
                case HomeopathyType.BowelMovements:
                    homeopathy.BowelMovements = model.JsonString;
                    break;
                case HomeopathyType.Urination:
                    homeopathy.Urination = model.JsonString;
                    break;
                case HomeopathyType.SweatFeverChill:
                    homeopathy.SweatFeverChill = model.JsonString;
                    break;
                case HomeopathyType.ChestHeartColdCough:
                    homeopathy.ChestHeartColdCough = model.JsonString;
                    break;
                case HomeopathyType.SexualSphere:
                    homeopathy.SexualSphere = model.JsonString;
                    break;
                case HomeopathyType.GeneralComplaints:
                    homeopathy.GeneralComplaints = model.JsonString;
                    break;
                case HomeopathyType.AffectedFactors:
                    homeopathy.AffectedFactors = model.JsonString;
                    break;
                case HomeopathyType.EmotionalNature:
                    homeopathy.EmotionalNature = model.JsonString;
                    break;
                case HomeopathyType.SleepAndDreams:
                    homeopathy.SleepAndDreams = model.JsonString;
                    break;
                case HomeopathyType.Children:
                    homeopathy.Children = model.JsonString;
                    break;
            }

            var updated = await this.unitOfWork.Homeopathy.UpdateAsync(homeopathy);
            response.Response = updated > 0 ? homeopathy.HomeopathyId : 0;
            return response;
        }

        /// <inheritdoc />
        public Task<int> DeleteAsync(int homeopathyId) => this.unitOfWork.Current.ExecuteAsync($@"DELETE FROM ""Homeopathy"" WHERE ""HomeopathyId""= {homeopathyId}");

        /// <inheritdoc />
        public Task<HomeopathyFullTranscriptModel> FindFullTranscriptAsync(int appointmentId)
        {
            var query = $@"SELECT A.""AppointmentId"",A.""AppointmentNo"",A.""AppointmentDate"",A.""AppointmentTime"", 
                            (case when A.""PatientFamilyId"" is not null then PF.""FullName"" else P.""FullName"" end) AS ""PatientName"", 
                           (case when A.""PatientFamilyId"" is not null then PF.""Gender"" else P.""Gender"" end) AS ""PatientGender"",C.""CountryCode"" AS ""PatientCountryCode"",
							P.""Mobile"" AS ""PatientMobile"",
                            (case when A.""PatientFamilyId"" is not null then PF.""Age"" else P.""Age"" end) AS ""PatientAge"", P.""DateOfBirth"" AS ""PatientDateOfBirth"",
                            CONCAT(Pr.""Salutation"",' ', Pr.""FullName"") AS ""ProviderName"",
							(CASE WHEN P.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', P.""Guid"", '/', P.""ThumbnailUrl"") ELSE NULL END) AS ""PatientThumbnailUrl"",
                            ""HomeopathyId"", ""Confidential"", ""CCAndOC"", ""AdditionalComplaints"", ""PastIllness"", ""FamilyIllness"", ""SpouseAndChildren"", ""PersonalHistory"", ""PersonalHabits"", ""AppetiteAndThirst"", ""BowelMovements"", ""Urination"", 
                            ""SweatFeverChill"", ""ChestHeartColdCough"", ""SexualSphere"", ""GeneralComplaints"", ""AffectedFactors"", ""EmotionalNature"", ""SleepAndDreams"", ""Children"", ATS.""Symptoms"" FROM ""Appointment"" A
							LEFT JOIN ""Homeopathy"" hm ON A.""AppointmentId""= hm.""AppointmentId""
                            LEFT JOIN ""Provider"" pr on pr.""ProviderId""=A.""ProviderId""
							LEFT JOIN ""AppointmentSymptom"" ATS ON  ATS.""AppointmentId"" = A.""AppointmentId""
							JOIN ""Patient"" P ON P.""PatientId"" = A.""PatientId""
                            Left join ""PatientFamily"" PF on PF.""PatientFamilyId"" = A.""PatientFamilyId""
							LEFT JOIN ""Country"" C ON C.""CountryId""=P.""CountryId""
                            where A.""AppointmentId"" = {appointmentId} AND A.""Active"" IS TRUE";
            return this.unitOfWork.Current.QueryFirstOrDefaultAsync<HomeopathyFullTranscriptModel>(query);
        }
    }
}