using Hims.Shared.UserModels.Common;

namespace Hims.Api.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading.Tasks;
    using DocumentFormat.OpenXml.Presentation;
    using Domain.Services;
    using Hims.Api.Helper;
    using Hims.Api.Models;
    using Hims.Api.Senders;
    using Hims.Domain.Configurations;
    using Hims.Domain.Entities;
    using Hims.Domain.Helpers;
    using Hims.Shared.Library.Enums;
    using Hims.Shared.UserModels;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Shared.DataFilters;
    using Shared.EntityModels;
    using Shared.UserModels.Filters;
    using Utilities;

    /// <inheritdoc />
    [Route("api/admissions")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class AdmissionsController : BaseController
    {
        /// <summary>
        /// The admission services.
        /// </summary>
        private readonly IAdmissionService admissionsServices;

        /// <summary>
        /// the patient service
        /// </summary>
        private readonly IPatientService patientServices;

        /// <summary>
        /// The auditlog services.
        /// </summary>
        private readonly IAuditLogService auditLogServices;

        /// <summary>
        /// The AES helper.
        /// </summary>
        private readonly IAESHelper aesHelper;

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

        /// <summary>
        /// The document helper.
        /// </summary>
        private readonly IDocumentHelper documentHelper;

        /// <summary>
        /// The application configuration.
        /// </summary>
        private readonly IApplicationConfiguration applicationConfiguration;

        /// <summary>
        /// The email sender.
        /// </summary>
        private readonly IEmailSender emailSender;

        /// <summary>
        /// The SMS sender.
        /// </summary>
        private readonly ISMSSender smsSender;

        /// <summary>
        /// The url shortner helper.
        /// </summary>
        private readonly IURLShortnerHelper uRLShortnerHelper;

        /// <summary>
        /// The whats application SMS sender
        /// </summary>
        private readonly IWhatsAppSMSSender whatsAppSMSSender;

        /// <summary>
        /// The charge module service.
        /// </summary>
        private readonly IChargeModuleService chargeModuleService;
        /// <summary>
        /// The patient document services.
        /// </summary>
        private readonly IPatientDocumentService patientDocumentServices;
        /// <summary>
        /// The running environment.
        /// </summary>
        private readonly IRunningEnvironment runningEnvironment;
        /// <summary>
        /// The FTP upload helper.
        /// </summary>
        private readonly IFtpUploadHelper ftpUploadHelper;

        /// <summary>
        /// The setting service
        /// </summary>
        private readonly ISettingService settingService;
        /// <inheritdoc />
        public AdmissionsController(
            IAdmissionService admissionsServices,
            IAmazonS3Configuration amazonS3Configuration,
            IAESHelper aesHelper,
            IAuditLogService auditLogServices,
            IPatientService patientServices, IDocumentHelper documentHelper, IApplicationConfiguration applicationConfiguration,
            IEmailSender emailSender,
            ISMSSender smsSender, IURLShortnerHelper uRLShortnerHelper,
            IWhatsAppSMSSender whatsAppSMSSender,
            IChargeModuleService chargeModuleService,
            IPatientDocumentService patientDocumentServices,
            IRunningEnvironment runningEnvironment, IFtpUploadHelper ftpUploadHelper, ISettingService settingService)
        {
            this.admissionsServices = admissionsServices;
            this.amazonS3Configuration = amazonS3Configuration;
            this.aesHelper = aesHelper;
            this.auditLogServices = auditLogServices;
            this.patientServices = patientServices;
            this.documentHelper = documentHelper;
            this.applicationConfiguration = applicationConfiguration;
            this.emailSender = emailSender;
            this.smsSender = smsSender;
            this.uRLShortnerHelper = uRLShortnerHelper;
            this.whatsAppSMSSender = whatsAppSMSSender;
            this.chargeModuleService = chargeModuleService;
            this.patientDocumentServices = patientDocumentServices;
            this.runningEnvironment = runningEnvironment;
            this.ftpUploadHelper = ftpUploadHelper;
            this.settingService = settingService;
        }

        /// <summary>
        /// The fetch Admissions.
        /// </summary>
        /// <param name="model">
        /// The admission filter model.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The list of Admissions.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of Admissions.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Route("fetch")]
        [ProducesResponseType(typeof(List<AdmissionModel>), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchAsync([FromBody] AdmissionFilterModel model, [FromHeader] LocationHeader header)
        {
            model = (AdmissionFilterModel)EmptyFilter.Handler(model);

            model.LocationId = model.LocationId <= 0 && !string.IsNullOrEmpty(header.LocationId)
               ? Convert.ToInt32(header.LocationId)
               : model.LocationId;

            var admissions = await this.admissionsServices.FetchAsync(model);
            foreach (var item in admissions.ToList())
            {
                item.EncryptedAdmissionId = this.aesHelper.Encode(item.AdmissionId.ToString());
                item.EncryptedPatientId = this.aesHelper.Encode(item.PatientId.ToString());

                //if (!string.IsNullOrEmpty(item.PatientThumbnailUrl))
                //{
                //    item.PatientThumbnailUrl = this.amazonS3Configuration.BucketURL + item.PatientThumbnailUrl;
                //}

                //if (!string.IsNullOrEmpty(item.ProviderThumbnailUrl))
                //{
                //    item.ProviderThumbnailUrl = this.amazonS3Configuration.BucketURL + item.ProviderThumbnailUrl;
                //}
            }
            return this.Success(admissions);
        }

        /// <summary>
        /// The fetch Admission.
        /// </summary>
        /// <param name="admissionId"></param>
        /// <param name="encryptedAdmissionId"></param>
        /// <returns>
        /// The Admission.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Admission model.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpGet]
        [Route("find")]
        [ProducesResponseType(typeof(AdmissionModel), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FindAsync(int admissionId, string encryptedAdmissionId)
        {
            if (encryptedAdmissionId != null)
            {
                admissionId = Convert.ToInt32(this.aesHelper.Decode(encryptedAdmissionId));
            }
            var admission = await this.admissionsServices.FindAsync(admissionId);
            admission.EncryptedAdmissionId = this.aesHelper.Encode(admission.AdmissionId.ToString());
            admission.EncryptedPatientId = this.aesHelper.Encode(admission.PatientId.ToString());

            return this.Success(admission);
        }

        /// <summary>
        /// The fetch Admissions.
        /// </summary>
        /// <param name="model">
        /// The admission filter model.
        /// </param>
        /// <returns>
        /// The list of Admissions.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of Admissions.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Route("cancel")]
        public async Task<ActionResult> CancelAsync([FromBody] IdModel model, [FromHeader] LocationHeader header)
        {
            try
            {
                var patientFullName = await this.patientServices.FindPatientByAdmissionId(model.Id);
                model.LocationId = int.Parse(header.LocationId);
                var response = await this.admissionsServices.CancelAsync(model.Id);

                try
                {

                    var auditLogModel = new AuditLogModel
                    {
                        AccountId = model.CreatedBy,
                        LogTypeId = (int)LogTypes.Admission,
                        LogFrom = (short)model.RoleId,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LogDescription = $" <b>{model.CreatedByName}</b> has cancelled the admission for the patient: <b>{patientFullName}</b>",
                        LocationId = model.LocationId
                    };

                    await this.auditLogServices.LogAsync(auditLogModel);

                }
                catch (Exception e)
                {
                    //audit
                }


                return this.Success(new GenericResponse
                {
                    Status = response > 0 ? GenericStatus.Success : GenericStatus.Warning
                });
            }
            catch (Exception ex)
            {
                return this.Success(new GenericResponse
                {
                    Status = GenericStatus.Error,
                    Message = ex.Message
                });
            }
        }

        /// <summary>
        /// The quick schedule, add patient and add admission.
        /// </summary>
        /// <param name="request">
        /// The add request model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Patient Added and added admission successfully.
        /// - 409 - Admission has already exist with us.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("quick-schedule")]
        [Consumes("multipart/form-data")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(typeof(string), 409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> QuickScheduleAsync([FromForm] NewPatientAdmissionModel request, [FromHeader] LocationHeader header)
        {
            request = (NewPatientAdmissionModel)EmptyFilter.Handler(request);


            var patientId = request.PatientId;
            if (request.PatientId == 0)
            {
                var patientModel = new PatientModel
                {
                    FirstName = request.FirstName,
                    LastName = request.LastName,
                    FatherOrHusband = request.FatherOrHusband,
                    Mobile = request.Mobile,
                    Age = request.Age,
                    CountryId = request.CountryId,
                    Email = request.Email,
                    CreatedBy = request.CreatedBy,
                    Gender = request.Gender,
                    AadharNo = request.AadharNo,
                    DateOfBirth = request.DateOfBirth,
                    AddressLine2 = request.AddressLine2,
                    Base64ProfileImage = request.Base64ProfileImage,
                    City = request.City,
                    ProfileImageUrl = request.ProfileImageUrl,
                    Salutation = request.Salutation,
                    State = request.State,
                    StreetAddress = request.StreetAddress,
                    ThumbnailUrl = request.ThumbnailUrl,
                    Zipcode = request.Zipcode,
                    ReferredBy = request.ReferredBy,
                    ReferredByName = request.ReferredByName,
                    RoleId = request.LogFrom,
                    CreatedByName = request.CreatedByName,
                    Education = request.Education,
                    Occupation = request.Occupation,
                    MartialStatus = request.MaritalStatus,
                    Religion = request.Religion,
                    Nationality = request.Nationality
                };

                patientModel.LocationId = int.Parse(header.LocationId);

                PatientFamilyModel pfModel = new PatientFamilyModel();
                pfModel.FullName = request.RelationName;
                pfModel.Education = request.RealtiveEducation;
                pfModel.DOB = Convert.ToDateTime(request.RelativeDateOfBirth);
                pfModel.ContactNo = request.RelativeMobile;
                pfModel.RelativeGender = request.RelativeGender;
                pfModel.Relation = request.Relation;
                pfModel.CreatedBy = request.CreatedBy;
                pfModel.CreatedDate = DateTime.UtcNow.AddMinutes(330);
                pfModel.Occupation = request.RelativeOccupation;
                patientModel.Email = string.IsNullOrEmpty(patientModel.Email) ? null : patientModel.Email;
                patientModel.FullName = CoreFilter.FullName(patientModel.FirstName, patientModel.MiddleName, patientModel.LastName);

                // var (newPatientId, guid) = await this.patientServices.AddPatientAsync(patientModel, pfModel);

                patientModel.Email = string.IsNullOrEmpty(patientModel.Email) ? null : patientModel.Email;
                patientModel.FullName = CoreFilter.FullName(patientModel.FirstName, patientModel.MiddleName, patientModel.LastName);

                var (accountId, newPatientId, guid) = await this.patientServices.AddAsync(patientModel, request.EmergencyContacts ?? new List<PatientEmergencyModel>(), request.Insurances ?? new List<PatientInsuranceModel>(), pfModel, request.RelativeDetails ?? new List<PatientFamilyModel>());

                //var (newPatientId, guid) = await this.patientServices.AddPatientAsync(patientModel,pfModel);
                patientId = newPatientId;
                switch (patientId)
                {
                    case -2:
                        return this.Conflict("Given email address has already been exists with us.");
                    case -1:
                        return this.Conflict("Given mobile number has already been exists with us.");
                    case 0:
                        return this.ServerError();
                }

                (patientModel.ProfileImageUrl, patientModel.ThumbnailUrl) = await this.documentHelper.UploadAsync(patientModel.Base64ProfileImage, (Guid)guid, "Profile", "profile_" + DateTime.UtcNow.Ticks);
                if (!string.IsNullOrEmpty(patientModel.ProfileImageUrl))
                {
                    await this.patientServices.UpdateImageUrlsAsync(patientModel, (Guid)guid);
                }

                var encryptedAccountId = this.aesHelper.Encode(patientId.ToString());
                var createPasswordLink = this.applicationConfiguration.CreatePasswordLink + encryptedAccountId;

                var shortnerUrl = await this.uRLShortnerHelper.MakeShorterUrl(createPasswordLink);

                if (!string.IsNullOrEmpty(patientModel.Email))
                {
                    var response = await this.emailSender.SendWelcomeMailAsync(patientModel.Email, patientModel.FullName, null, createPasswordLink);
                    //return response ? this.Success("User details has been added successfully.") : this.Success(this.MailServerError());
                }
                else
                {
                    var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                    var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                    if ((bool)WhatsAppMessage[0].Active)
                    {
                        bool ret = await this.whatsAppSMSSender.SendRegisteredMessage(patientModel.Mobile, patientModel.FullName);
                    }
                    try
                    {
                        var smsSent = await this.smsSender.SendWelcomeMessageAsync(patientModel.Mobile, patientModel.FullName, null, shortnerUrl, Convert.ToInt32(patientModel.CountryId));
                        //return smsSent ? this.Success("Patient has been added successfully.") : this.Success(this.SMSServerError());
                    }
                    catch (Exception e)
                    {
                        //sms error ignore
                    }
                }

                try
                {
                    var auditLogModel = new AuditLogModel
                    {
                        AccountId = patientModel.CreatedBy,
                        LogTypeId = (int)LogTypes.Patient,
                        LogFrom = (short)patientModel.RoleId,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LogDescription = $@"{patientModel.CreatedByName} <b>Added</b> Patient:<b> {patientModel.FullName}</b> <br> Successfully",
                        LocationId = patientModel.LocationId
                    };
                    await this.auditLogServices.LogAsync(auditLogModel);

                }
                catch (Exception e)
                {
                    //audit
                }
            }

            var admissionModel = new ModifyAdmissionModel
            {
                Active = true,
                AdmissionDate = request.AdmissionDate,
                AdmissionTime = request.AdmissionTime,
                AdmissionTimeString = request.AdmissionTimeString,
                ProviderId = request.ProviderId,
                PatientId = (int)patientId,
                DepartmentId = request.DepartmentId,
                PatientType = request.PatientType,
                AdmissionNotes = request.AdmissionNotes,
                BabysBirthDate = request.BabysBirthDate,
                BabysBirthTime = request.BabysBirthTime,
                BabysFathersName = request.BabysFathersName,
                BabysGender = request.BabysGender,
                BabysMothersAdmissionNo = request.BabysMothersAdmissionNo,
                BabysSurgeryType = request.BabysSurgeryType,
                BedId = request.BedId,
                EncounterId = request.EncounterId,
                IsDischarged = request.IsDischarged,
                IsMaternity = request.IsMaternity,
                PatientFamilyId = request.PatientFamilyId,
                ReadyforDischarge = request.ReadyforDischarge,
                SurgeryTypeId = request.SurgeryTypeId,
                //EmergencyNo = request.EmergencyNo,
                //EmergencyType = request.EmergencyType,
                AttendantName = request.AttendantName,
                AttendantContactNo = request.AttendantContactNo,
                AttendantRelationWithPatient = request.AttendantRelationWithPatient,
                LogFrom = request.LogFrom,
                CreatedBy = request.CreatedBy,
                VisitTypeId = request.VisitTypeId,
                IsConvertedFromOPtoIp = request.IsConvertedFromOPtoIp ?? false,
            };

            await this.ModifyAdmissionAsync(admissionModel, header);
            return this.Success("Patient has been added and admission added successfully.");
        }

        /// <summary>
        /// The add submission.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Admission added successfully.
        /// - 409 - Admission already exist.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("modify-admission")]
        [Consumes("multipart/form-data")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> ModifyAdmissionAsync([FromForm] ModifyAdmissionModel model, [FromHeader] LocationHeader header)
        {

            model = (ModifyAdmissionModel)EmptyFilter.Handler(model);
            model.AdmissionTime = TimeSpan.Parse(model.AdmissionTimeString);
            model.LocationId = Convert.ToInt32(header.LocationId);
            var files = this.Request.Form.Files;
            model.Files = files;
            var defaultTimes = ProgressReportHelper.GetDefaultTimes();

            if (model.BreakfastStr != null)
            {
                var defaultMorning = new TimeSpan(defaultTimes.Morning.Hour, defaultTimes.Morning.Minute, 0);
                var newMorning = TimeSpan.Parse(model.BreakfastStr);
                model.Breakfast = TimeSpan.Compare(newMorning, defaultMorning) == 0
                    ? (TimeSpan?)null : newMorning;
            }
            if (model.LunchStr != null)
            {
                var defaultAfternoon = new TimeSpan(defaultTimes.Afternoon.Hour, defaultTimes.Afternoon.Minute, 0);
                var newAfternoon = TimeSpan.Parse(model.LunchStr);
                model.Lunch = TimeSpan.Compare(newAfternoon, defaultAfternoon) == 0
                    ? (TimeSpan?)null : newAfternoon;
            }
            if (model.DinnerStr != null)
            {
                var defaultNight = new TimeSpan(defaultTimes.Night.Hour, defaultTimes.Night.Minute, 0);
                var newNight = TimeSpan.Parse(model.DinnerStr);
                model.Dinner = TimeSpan.Compare(newNight, defaultNight) == 0
                    ? (TimeSpan?)null : newNight;
            }

            var admissionId = await this.admissionsServices.AddAdmissionAsync(model);
            switch (admissionId)
            {
                case -1:
                    return this.Conflict("This patient already has admission and not discharged!.");
                case 0:
                    return this.ServerError();
                case 2:
                    return this.Conflict("This bed is not available.");
                default:
                    try
                    {
                        var getAdmissionInfo = await this.admissionsServices.FetchAdmissionInfo(admissionId);
                        if (getAdmissionInfo != null)
                        {
                            var modifiedName = "Updated by " + getAdmissionInfo.ModifiedByName + "(" + getAdmissionInfo.ModifiedByRoleName + ")";
                            if (model.AdmissionId == 0)
                            {
                                modifiedName = "Added by " + getAdmissionInfo.CreatedByName + "(" + getAdmissionInfo.CreatedByRoleName + ")";
                            }
                            var auditLogModel = new AuditLogModel
                            {
                                AccountId = model.AdmissionId == 0 ? model.CreatedBy : model.ModifiedBy,
                                LogTypeId = (int)LogTypes.Admission,
                                LogFrom = model.LogFrom,
                                LogDate = DateTime.UtcNow.AddMinutes(330),
                                LogDescription = $@"<b>Admission</b> for Patient: <b>{getAdmissionInfo.PatientName}</b> has been {modifiedName}<br>
                                                    on {model?.AdmissionDate.ToString("MM/dd/yyyy")} with Admission No:<b>{getAdmissionInfo.AdmissionNo}</b>",
                                LocationId = model.LocationId
                            };
                            await this.auditLogServices.LogAsync(auditLogModel);
                        }
                    }
                    catch (Exception e)
                    {
                        //ignore for auditlog
                    }

                    
                    return this.Success("Admission added successfully!!");

            }

        }

        /// <summary>
        /// The fetch wards.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns list of wards.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-wards")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchWardsAsync([FromHeader] LocationHeader header)
        {
            int locationId = Convert.ToInt32(header.LocationId);
            var wards = await this.admissionsServices.FetchWardsAsync(locationId);
            return this.Success(wards);
        }

        /// <summary>
        /// The fetch rooms.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns list of rooms.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("fetch-rooms")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchRoomsAsync([FromBody] BedManagementModel model)
        {
            model = (BedManagementModel)EmptyFilter.Handler(model);
            //model.LocationId = Convert.ToInt32(header.LocationId);
            var rooms = await this.admissionsServices.FetchRoomsAsync(model.WardId, model.ChargeCategoryId, model.LocationId);
            return this.Success(rooms);
        }


        /// <summary>
        /// Fetches the priorities asynchronous.
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        [Route("fetch-priorities")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchPrioritiesAsync()
        {
            try
            {
                var records = await this.admissionsServices.FetchPrioritiesAsync();
                return this.Success(new GenericResponse
                {
                    Status = GenericStatus.Success,
                    Data = records
                });
            }
            catch (Exception)
            {
                return this.Success(new GenericResponse
                {
                    Status = GenericStatus.Error
                });
            }
        }

        /// <summary>
        /// The fetch beds.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns list of beds.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("fetch-beds")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchBedsAsync([FromBody] BedManagementModel model, [FromHeader] LocationHeader location)
        {
            model = (BedManagementModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(location.LocationId);

            var getModulesData = await this.chargeModuleService.GetRequiredDetailForChargeFetchAsync("room", (int)model.LocationId);
            if (getModulesData == null)
            {
                return this.Success(new List<BedManagementModel>());
            }
            else
            {
               // model.ChargeModuleTemplateId = getModulesData.ChargeModuleTemplateId;
                model.ModulesMasterId = getModulesData.ModulesMasterId;
            }

            var beds = await this.admissionsServices.FetchBedsAsync(model);
            return this.Success(beds);
        }

        /// <summary>
        /// The generate transaction id.
        /// </summary>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private static string GenerateTransactionId()
        {
            var rnd = new Random();
            var strHash = GenerateHash(rnd.ToString() + DateTime.UtcNow);
            return strHash.Substring(0, 20);
        }

        /// <summary>
        /// The generate hash.
        /// </summary>
        /// <param name="text">
        /// The text.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private static string GenerateHash(string text)
        {
            var message = Encoding.UTF8.GetBytes(text);
            var hashString = new SHA512Managed();
            var hashValue = hashString.ComputeHash(message);
            return hashValue.Aggregate(string.Empty, (current, x) => current + $"{x:x2}");
        }

        /// <summary>
        /// To check follow up available for patient with selected doctor.
        /// </summary>
        /// <param name="model">
        /// The appointment request model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns follow up details.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("check-follow-up-for-ip")]
        [ProducesResponseType(200, Type = typeof(AdmissionModel))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> CheckFollowUpForPatientAsync([FromBody] AdmissionModel model)
        {
            var recentAppointment = await this.patientServices.CheckForFollowUpForInPatientAsync(model);
            return this.Success(recentAppointment);
        }

        /// <summary>
        /// Updates the discharg date asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        [Route("update-discharg-date")]
        public async Task<ActionResult> UpdateDischargDateAsync([FromBody] UpdateExpectedDischargeDateModel model)
        {
            var response = await this.patientServices.UpdateDischargDateAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Raises the bed change request asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        [Route("raise-bed-change-request")]
        public async Task<ActionResult> RaiseBedChangeRequestAsync([FromBody] AdmissionBedChangeRequestModel model)
        {
            model = (AdmissionBedChangeRequestModel)EmptyFilter.Handler(model);
            var response = await this.admissionsServices.RaiseBedChangeRequestAsync(model);
            return this.Success(response);
        }


        /// <summary>
        /// The insert cubicle async.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("insert-admission-transfer-request")]
        public async Task<ActionResult> InsertAsync([FromBody] AdmissionTransferRequestModel model)
        {
            model = (AdmissionTransferRequestModel)EmptyFilter.Handler(model);
            var response = await this.admissionsServices.AddAdmissionTransferRequest(model);
            return this.Success(response);


        }
        /// <summary>
        /// The fetch cubicles.
        /// </summary>
        /// <param name="model">
        /// The widget filter model.
        /// </param>
        /// <returns>
        /// The list of cubicle.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of cubicles.
        /// - 500 - Problem with Server side code.
        /// </remarks>

        [HttpPost]
        [Route("fetch-admission-transfer-request")]
        public async Task<ActionResult> FetchAdmissionTransferRequest([FromBody] AdmissionTransferRequestModel model, [FromHeader] LocationHeader location)
        {
            
                model.LocationId = Convert.ToInt32(location.LocationId);
                var records = await this.admissionsServices.FetchAdmissionTransferRequest(model);
                foreach(var item in records)
                {
                    if(item.ChargeCategories != null)
                    {
                        item.ChargeCategories = item.ChargeCategories.Replace("{", string.Empty);
                        item.ChargeCategories = item.ChargeCategories.Replace("}", string.Empty);
                    }
                }
                return Success(records);
            
        }
        /// <summary>
        /// The fetch cubicles.
        /// </summary>
        /// <param name="model">
        /// The widget filter model.
        /// </param>
        /// <returns>

        [HttpPost]
        [Route("accept-admission-transfer-request")]
        public async Task<ActionResult> AcceptTransferRequest([FromBody] AdmissionTransferRequestModel model)
        {

            var records = await this.admissionsServices.AcceptTransferRequest(model);
            return Success(records);

        }
        /// <summary>
        /// The fetch cubicles.
        /// </summary>
        /// <param name="model">
        /// The widget filter model.
        /// </param>
        /// <returns>

        [HttpPost]
        [Route("reject-admission-transfer-request")]
        public async Task<ActionResult> RejectAdmissionTransferRequest([FromBody] AdmissionTransferRequestModel model)
        {

            var records = await this.admissionsServices.RejectAdmissionTransferRequest(model);
            return Success(records);

        }
    }
}