namespace Hims.Api.Controllers
{
    using System.Threading.Tasks;

    using Domain.Services;
    using Domain.Configurations;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;

    using Shared.DataFilters;
    using Shared.EntityModels;
    using Shared.UserModels.Laboratory;
    using Shared.UserModels.Labs;
    using System.Collections.Generic;

    using Utilities;
    using Hims.Shared.Library.Enums;
    using System;
    using System.Linq;
    using Hims.Domain.Helpers;
    using Hims.Shared.UserModels.ChargeModule;
    using Hims.Shared.UserModels.ServiceOrder;
    using Senders;
    using Hims.Api.Models;
    using Newtonsoft.Json;
    using Hims.Shared.UserModels.Labs.Report;

    /// <inheritdoc />
    [Authorize]
    [Route("api/labs")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class LabsController : BaseController
    {
        /// <summary>
        /// The laboratory department service.
        /// </summary>
        private readonly ILabDepartmentService laboratoryDepartmentService;

        /// <summary>
        /// The labs service.
        /// </summary>
        private readonly ILabsService labsService;

        /// <summary>
        /// The laboratory service.
        /// </summary>
        private readonly ILabLogService labLogService;

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

        /// <summary>
        /// The ftp helper.
        /// </summary>
        private readonly IFtpHelper ftpHelper;

        /// <summary>
        /// The charge module service.
        /// </summary>
        private readonly IChargeModuleService chargeModuleService;

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

        /// <summary>
        /// The resource service
        /// </summary>
        private readonly IResourceService resourceService;

        /// <summary>
        /// The laboratory vacutainer service.
        /// </summary>
        private readonly ILabVacutainerService laboratoryVacutainerService;

        /// <summary>
        /// The push notification helper.
        /// </summary>
        private readonly IPushNotificationHelper pushNotificationHelper;

        /// <summary>
        /// The account session services.
        /// </summary>
        private readonly IAccountSessionService accountSessionServices;

        /// <summary>
        /// The setting service
        /// </summary>
        private readonly ISettingService settingService;

        /// <inheritdoc />
        public LabsController(ILabLogService labLogService, ILabDepartmentService laboratoryDepartmentService, ILabsService labsService, IAESHelper aesHelper, IFtpHelper ftpHelper, IChargeModuleService chargeModuleService, IWhatsAppSMSSender whatsAppSMSSender, IResourceService resourceService, ILabVacutainerService laboratoryVacutainerService, IPushNotificationHelper pushNotificationHelper,IAccountSessionService accountSessionServices, ISettingService settingService)
        {
            this.labLogService = labLogService;
            this.laboratoryDepartmentService = laboratoryDepartmentService;
            this.labsService = labsService;
            this.aesHelper = aesHelper;
            this.ftpHelper = ftpHelper;
            this.chargeModuleService = chargeModuleService;
            this.whatsAppSMSSender = whatsAppSMSSender;
            this.resourceService = resourceService;
            this.laboratoryVacutainerService = laboratoryVacutainerService;
            this.pushNotificationHelper = pushNotificationHelper;
            this.accountSessionServices = accountSessionServices;
            this.settingService = settingService;
        }

        /// <summary>
        /// The insert lab units async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("create-unit")]
        public async Task<ActionResult> InsertLabUnitsAsync([FromBody] LookupValueModel model, [FromHeader] LocationHeader header)
        {
            model = (LookupValueModel)EmptyFilter.Handler(model);
            var response = await this.labsService.CreateUnitAsync(model);
            var locationId = Convert.ToInt32(header.LocationId);

            if (response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.LoginAccountId,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Unit,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.UtcNow,
                    LocationId = locationId,
                    LogDescription = $@"'{model.AccountFullName}' has added new unit '{model.Name}'"
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);

        }

        /// <summary>
        /// Fetches all parameter methods.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-all-parameter")]
        public async Task<ActionResult> FetchAllParameterMethods()
        {
            return this.Success(await this.labsService.FetchAllParameterMethod());
        }

        /// <summary>
        /// Modifies the lab departments asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-lab-department")]
        public async Task<ActionResult> ModifyLabDepartmentsAsync([FromBody] LabDepartmentModel model, [FromHeader] LocationHeader location)
        {
            model = (LabDepartmentModel)EmptyFilter.Handler(model);
            var response = await this.laboratoryDepartmentService.ModifyDepartmentAsync(model);

            string message;
            switch (response)
            {
                case -1:
                case -2:
                    message = "The department name already exists";
                    break;
                case -3:
                    message = "Previous record not found for update";
                    break;
                case int n when n > 0:
                    var labLogModel = new LabLogModel
                    {
                        AccountId = model.CreatedBy,
                        LabLogTypeId = (int)LabLogTypes.LabDepartment,
                        LogFrom = model.LoginRoleId > 0 ? (short)model.LoginRoleId : short.Parse(1.ToString()),
                        LogDate = DateTime.UtcNow,
                        LocationId = int.Parse(location.LocationId),
                        LogDescription = $@"Department : <b>{model.DepartmentName}</b> successfully {(model.LabDepartmentId > 0 ? "Updated" : "Added")} into Labs by {model.CreatedByName}"
                    };
                    await this.labLogService.LogAsync(labLogModel);
                    message = $@"Successfully {(model.LabDepartmentId > 0 ? "updated" : "created")}";
                    break;
                default:
                    message = "Error occured";
                    break;
            }

            return this.Success(message);
        }

        /// <summary>
        /// Fetches the lab departments asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-lab-departments")]
        public async Task<ActionResult> FetchLabDepartmentsAsync([FromBody] LabDepartmentModel model)
        {
            model ??= new LabDepartmentModel();
            var response = await this.laboratoryDepartmentService.FetchAllDepartmentAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab departments asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-lab-departments-status")]
        public async Task<ActionResult> FetchLabDepartmentsAsync([FromBody] LabDepartmentModel model, [FromHeader] LocationHeader location)
        {
            model = (LabDepartmentModel)EmptyFilter.Handler(model);
            var response = await this.laboratoryDepartmentService.ModifyLabStatus(model);
            if (response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.LabDepartment,
                    LogFrom = model.LoginRoleId > 0 ? (short)model.LoginRoleId : short.Parse(1.ToString()),
                    LogDate = DateTime.UtcNow,
                    LocationId = int.Parse(location.LocationId),
                    LogDescription = $@"Department : <b>{model.DepartmentName}</b> successfully {((bool)model.Active ? "Activated" : "Deactivated")} by {model.CreatedByName}"
                };
                await this.labLogService.LogAsync(labLogModel);
            }

            return this.Success(response);
        }

        /// <summary>
        /// Modifies the lab parameters.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-lab-parameter")]
        public async Task<ActionResult> ModifyLabParameters([FromBody] LabParameterModel model, [FromHeader] LocationHeader location)
        {
            model = (LabParameterModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ModifyLabParameteresAsync(model);
            if (model.LabParameterHeaderId == 0 && response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Parameter,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has added <b>Parameter</b> of <strong>{model.ParameterName}</strong> successfully.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            else if (model.LabParameterHeaderId > 0 && response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Parameter,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has Updated <b>Parameter</b> of <strong>{model.ParameterName}</strong> successfully.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab parameter headers asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-lab-parameter-header")]
        public async Task<ActionResult> FetchLabParameterHeadersAsync([FromBody] LabParameterModel model)
        {
            model ??= new LabParameterModel();
            var response = await this.labsService.FetchLabParameterHeaderAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab parameter details asynchronous.
        /// </summary>
        /// <param name="headerId">The header identifier.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-lab-parameter-detail")]
        public async Task<ActionResult> FetchLabParameterDetailsAsync(int headerId)
        {
            if (headerId == 0)
            {
                return this.BadRequest("Invalid input");
            }
            var response = await this.labsService.FetchLabParameterDetailAsync(headerId);
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the lab components asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-lab-component")]
        public async Task<ActionResult> ModifyLabComponentsAsync([FromBody] LabComponentModel model, [FromHeader] LocationHeader location)
        {
            model = (LabComponentModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ModifyLabComponentsAsync(model);
            if (model.LabComponentHeaderId == 0 && response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Component,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has added <b>Component</b> of <strong>{model.ComponentName}</strong> successfully.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            else if (model.LabComponentHeaderId > 0 && response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Component,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has Updated <b>Component</b> of <strong>{model.ComponentName}</strong> successfully.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab components headers asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-lab-component-header")]
        public async Task<ActionResult> FetchLabComponentsHeadersAsync([FromBody] LabComponentModel model)
        {
            model ??= new LabComponentModel();
            var response = await this.labsService.FetchLabComponentHeaderAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab component details asynchronous.
        /// </summary>
        /// <param name="headerId">The header identifier.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-lab-component-detail")]
        public async Task<ActionResult> FetchLabComponentDetailsAsync(int headerId)
        {
            if (headerId == 0)
            {
                return this.BadRequest("Invalid input");
            }
            var response = await this.labsService.FetchLabComponentDetailAsync(headerId);
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the lab templates asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-lab-template")]
        public async Task<ActionResult> ModifyLabTemplatesAsync([FromBody] LabTemplateModel model, [FromHeader] LocationHeader location)
        {
            model = (LabTemplateModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ModifyTemplateAsync(model);
            if (model.LabTemplateHeaderId == 0 && response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Template,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has added <b>Template</b> of <strong>{model.TemplateName}</strong> successfully.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            else if (model.LabTemplateHeaderId > 0 && response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Template,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has Updated <b>Template</b> of <strong>{model.TemplateName}</strong> successfully.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the template header asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-lab-template-header")]
        public async Task<ActionResult> FetchTemplateHeaderAsync([FromBody] LabTemplateModel model)
        {
            model = (LabTemplateModel)EmptyFilter.Handler(model);
            var response = await this.labsService.FetchLabTemplateHeaderAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab template details asynchronous.
        /// </summary>
        /// <param name="headerId">The header identifier.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-lab-template-detail")]
        public async Task<ActionResult> FetchLabTemplateDetailsAsync(int headerId)
        {
            if (headerId == 0)
            {
                return this.BadRequest("Invalid input");
            }
            var response = await this.labsService.FetchLabTemplateDetailAsync(headerId);
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the lab main detail asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-main-lab-detail")]
        public async Task<ActionResult> ModifyLabMainDetailAsync([FromBody] LabMainDetailModel model, [FromHeader] LocationHeader location)
        {
            model = (LabMainDetailModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(location.LocationId);
            var response = await this.labsService.ModifyLabMaster(model);
            if (model.LabMainDetailId == 0 && response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Lab,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has added <b>Template</b> of <strong>{model.TestName}</strong> successfully.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            else if (model.LabMainDetailId > 0 && response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Lab,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has Updated <b>Template</b> of <strong>{model.TestName}</strong> successfully.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            var message = string.Empty;

            switch (response)
            {
                case -1:
                    message = "Error occurred in creating sample type.";
                    break;
                case -2:
                    message = "The given test name already exists, Please Import";
                    break;
                case -3:
                    message = "Error occurred while creating lab charges";
                    break;
                case -4:
                    message = "Error occurred while grouping lab templates";
                    break;
                case -5:
                    message = "Error occurred while creating lab";
                    break;
                case -6:
                    message = "Unable to find ModulesMasterId";
                    break;
            }

            return response > 0 ? this.Success(response) : this.BadRequest(message);
        }

        /// <summary>
        /// Fetches all sample types asynchronous.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("sample-types")]
        public async Task<ActionResult> FetchAllSampleTypesAsync()
        {
            return this.Success(await this.labsService.FetchAllSampleTypeAsync());
        }

        /// <summary>
        /// Fetches all lab main detail asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-main-lab-detail")]
        public async Task<ActionResult> FetchAllLabMainDetailAsync([FromBody] LabMainDetailModel model, [FromHeader] LocationHeader location)
        {
            model ??= new LabMainDetailModel();
            model.LocationId = !string.IsNullOrEmpty(model.FromSource) ? (int?)null : Convert.ToInt32(location.LocationId);
            var response = await this.labsService.FetchAllLabMainDetailAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab tagged templates asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-lab-tagged-templates")]
        public async Task<ActionResult> FetchLabTaggedTemplatesAsync([FromBody] LabMainDetailTemplateModel model)
        {
            model ??= new LabMainDetailTemplateModel();
            var response = await this.labsService.FetchLabTaggedTemplates(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab with charge asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-lab-with-charges")]
        public async Task<ActionResult> FetchLabWithChargeAsync([FromBody] LabMainDetailModel model, [FromHeader] LocationHeader location)
        {
            model ??= new LabMainDetailModel();
            model.LocationId = Convert.ToInt32(location.LocationId);
            var response = await this.labsService.FetchAllLabMainDetailAsync(model);

            var getModulesData = await this.chargeModuleService.GetRequiredDetailForChargeFetchAsync("lab", (int)model.LocationId);
            if (model.ChargeCategoryId != null && model.ChargeCategoryId > 0)
            {
                getModulesData.ChargeCategoryId = model.ChargeCategoryId;
            }
            if (getModulesData == null)
            {
                return this.Success(new List<LabMainDetailModel>());
            }

            foreach (var lab in response)
            {
                lab.Charges = new List<ChargeModuleDetailsModel>();
                getModulesData.ReferenceId = lab.LabMainDetailId;
                lab.Charges = (await this.chargeModuleService.FetchGivenChargesAsync(getModulesData)).ToList();
            }

            return this.Success(response);
        }

        /// <summary>
        /// Modifies the lab parameter status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-parameter-status")]
        public async Task<ActionResult> ModifyLabParameterStatusAsync([FromBody] LabParameterModel model, [FromHeader] LocationHeader location)
        {
            model = (LabParameterModel)EmptyFilter.Handler(model);

            var response = await this.labsService.ModifyParameterStatusAsync(model);
            if (response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.ModifiedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Parameter,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has changed status of <b>Parameter</b> - <strong>{model.ParameterName}</strong> on {DateTime.Now}",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the lab component status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-component-status")]
        public async Task<ActionResult> ModifyLabComponentStatusAsync([FromBody] LabComponentModel model, [FromHeader] LocationHeader location)
        {
            model = (LabComponentModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ModifyComponentStatusAsync(model);
            if (response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.ModifiedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Component,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has changed status of <b>Component</b> - <strong>{model.ComponentName}</strong> on {DateTime.Now}",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the lab template status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-template-status")]
        public async Task<ActionResult> ModifyLabTemplateStatusAsync([FromBody] LabTemplateModel model, [FromHeader] LocationHeader location)
        {
            model = (LabTemplateModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ModifyTemplateStatusAsync(model);
            if (response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.ModifiedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Template,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has changed status of <b>Template</b> - <strong>{model.TemplateName}</strong> on {DateTime.Now}",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the lab Detail status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-LabMainDetail-Status")]
        public async Task<ActionResult> ModifyLabMainDetailStatusAsync([FromBody] LabMainDetailModel model, [FromHeader] LocationHeader location)
        {
            model = (LabMainDetailModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ModifyLabMainDetailStatusAsync(model);
            if (response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.ModifiedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Masters_Lab,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.ModifiedByName} has changed status of <b>Test</b> - <strong>{model.TestName}</strong> on {DateTime.Now}",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);
        }

        /// <summary>Fetchlabs the bookings.</summary>
        /// <param name="model">The model.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        [HttpPost]
        [Route("fetch-Lab-bookings")]
        public async Task<ActionResult> FetchlabBookings([FromBody] LabBookingModel model)
        {
            model = (LabBookingModel)EmptyFilter.Handler(model);

            var responses = await this.labsService.FetchLabBookings(model);
            foreach (var resource in responses)
            {
                resource.EncryptedId = this.aesHelper.Encode(resource.PatientId.ToString());
            }
            return this.Success(responses);
        }

        /// <summary>Cancels the booked lab.</summary>
        /// <param name="model">The model.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        [HttpPost]
        [Route("lab-cancel")]
        [Consumes("multipart/form-data")]
        public async Task<ActionResult> CancelBookedLab([FromForm] LabBookingModel model)
        {
            model = (LabBookingModel)EmptyFilter.Handler(model);
            model.Labs = model.Labs.Count > 0 ? model.Labs : JsonConvert.DeserializeObject<List<NewLabBookingDetailModel>>(model.LabList);
            var result = await this.labsService.LabBookingsCancelling(model);
            if (result > 0)
            {
                string content = "";
                if (model.index != null)
                {
                    content = $@" in {model.RequisitionNumber}";
                }
                else
                {
                    content = $@"of {model.RequisitionNumber}";
                }
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.Lab_Cancelling_Test,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has Cancelled <b>Lab Bill</b> {content} <strong>{model.PatientName}</strong> successfully.",
                    LocationId = Convert.ToInt32(model.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);

                var accountSessionPatientModel = await this.accountSessionServices.FetchDeviceTokenAsync((int)model.PatientId, Roles.Patient);
                var accountSessionModels = accountSessionPatientModel as AccountSessionModel[] ?? accountSessionPatientModel.ToArray();
                if (accountSessionModels.Any())
                {
                    var deviceTokenForProviderAndroid = accountSessionModels.Where(d => d.DeviceType == 2).Select(s => s.DeviceToken).ToList();
                    var deviceTokenForProviderIOS = accountSessionModels.Where(d => d.DeviceType == 3).Select(s => s.DeviceToken).ToList();
                    if (model.PatientId != null)
                    {
                        string TestName = "";
                        var Labs = model.Labs.ToList();
                        string NotificationText = "";
                        if (model.index != null)
                        {
                            NotificationText = $@"Cancellation Success for lab test(s) " + model.Labs[(int)model.index].TestName.ToUpper() + "";

                        }
                        else
                        {
                            for (int i = 0; i < Labs.Count; i++)
                            {
                                TestName = TestName + Labs[i].TestName;
                                if (i != Labs.Count - 1)
                                {
                                    TestName = TestName + ", ";
                                }
                            }
                            NotificationText = $@"Cancellation Success for lab test(s) " + TestName.ToUpper() + "";
                        }
                        //foreach (var lab in Labs)
                        //{
                        //    TestName = TestName + lab.TestName  ;
                        //}
                        //for (int i =0; i<Labs.Count; i++)
                        //{
                        //    TestName = TestName + Labs[i].TestName;
                        //    if ( i != Labs.Count-1)
                        //    {
                        //        TestName = TestName + ", ";
                        //    }
                        //}
                        if (deviceTokenForProviderAndroid.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                NotificationText,
                                "LabCancelled",
                                deviceTokenForProviderAndroid,
                                new List<string>(),
                                model.RequisitionNumber,
                                DateTime.Now.ToString(),
                                null);
                        }

                        if (deviceTokenForProviderIOS.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                NotificationText,
                                "LabCancelled",
                                new List<string>(),
                                deviceTokenForProviderIOS,
                                model.RequisitionNumber,
                                DateTime.Now.ToString(),
                                null);
                        }
                    }
                }
                var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                if ((bool)WhatsAppMessage[0].Active)
                {
                    string LabName = "";
                    if (model.index != null)
                    {
                        LabName = model.Labs[(int)model.index].TestName;
                    }
                    else
                    {
                        foreach (var lab in model.Labs)
                        {
                            LabName += lab.TestName;
                            LabName += ", ";
                        }
                        LabName = LabName.Remove(LabName.Length - 2);
                    }
                    bool ret = await this.whatsAppSMSSender.SendLabCancellingWhatsAppMessage(model.Mobile, model.PatientName, LabName, model.RequisitionNumber);
                }
                
            }

            return this.Success(result);
        }

        /// <summary>Fetches the cancelled lab bill asynchronous.</summary>
        /// <param name="model">The model.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        [AllowAnonymous]
        [HttpPost]
        [Route("fetch-cancelled-lab-bill")]
        public async Task<ActionResult> FetchCancelledLabBillAsync([FromBody] LabBookingModel model)
        {
            model = (LabBookingModel)EmptyFilter.Handler(model);
            var response = await this.labsService.FetchCancelledLabBillAsync(model);
            return this.Success(response);
        }

        /// <summary>Fetches the selected lab data.</summary>
        /// <param name="model">The model.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        [HttpPost]
        [Route("fetch-selected-lab-data")]
        public async Task<ActionResult> FetchSelectedLabData([FromBody] LabBookingModel model)
        {
            model = (LabBookingModel)EmptyFilter.Handler(model);
            var response = await this.labsService.FetchSelectedLabDataAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches all lab status.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-lab-status")]
        public async Task<ActionResult> FetchAllLabStatus()
        {
            return this.Success(await this.labsService.FetchAllLabStatus());
        }

        /// <summary>
        /// Edits the color of the status.
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("update-status-colour")]
        public async Task<ActionResult> EditStatusColor([FromBody] LabBookingAllStatusModel model)
        {
            model = (LabBookingAllStatusModel)EmptyFilter.Handler(model);
            var response = await this.labsService.UpdateStatusColorAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches all charge categories.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-all-charge-categories")]
        public async Task<ActionResult> FetchAllChargeCategories()
        {
            return this.Success(await this.labsService.FetchAllLabChargeCategories());
        }

        /// <summary>
        /// Fetches the available import labs.
        /// </summary>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-available-import-labs")]
        public async Task<ActionResult> FetchAvailableImportLabs([FromHeader] LocationHeader location)
        {
            int locationId = Convert.ToInt32(location.LocationId);
            var response = await this.labsService.FetchAllAvailableImportLabAsync(locationId);
            return this.Success(response);
        }

        /// <summary>
        /// Imports the lab.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("import-lab")]
        public async Task<ActionResult> ImportLab([FromBody] NewLabImportModel model, [FromHeader] LocationHeader location)
        {
            model = (NewLabImportModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(location.LocationId);
            var response = await this.labsService.ImportLabAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the result parameter added labs asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-result-added-labs")]
        public async Task<ActionResult> FetchResultParameterAddedLabsAsync([FromBody] LabTransferModel model, [FromHeader] LocationHeader location)
        {
            model = (LabTransferModel)EmptyFilter.Handler(model);
            model.TransferedLocationId = Convert.ToInt32(location.LocationId);
            var response = await this.labsService.FetchResultAddedLabsAsync(model);
            var responseList = new List<LabTransferModel>();

            if (response.Count() > 0)
            {
                responseList = response.ToList();
                foreach (var record in responseList)
                {
                    record.EncryptedAppointmentId = this.aesHelper.Encode(record.AppointmentId.ToString());
                }
            }

            return this.Success(response);
        }

        /// <summary>
        /// Labs the doctor assign.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("lab-doctor-assign")]
        public async Task<ActionResult> LabDoctorAssign([FromBody] LabReportVerificationModel model)
        {
            model = (LabReportVerificationModel)EmptyFilter.Handler(model);
            var result = await this.labsService.AssignLabReportAsync(model);
            return this.Success(result);
        }

        /// <summary>
        /// Labs the doctor verification.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("doctor-verify-report")]
        public async Task<int> LabDoctorVerification([FromBody] LabDoctorVerificationModel model, [FromHeader]LocationHeader location)
        {
            model = (LabDoctorVerificationModel)EmptyFilter.Handler(model);
            var result = await this.labsService.DoctorVerificationLabReportAsync(model);
            //If result is 1 means the lab status is verifies, else 2 then it has  more doctors need to approve this lab result.
            if (result == 1)
            {
                var patientdetails = await this.resourceService.FetchPatientDetails((int)model.PatientId);
                string labLink = model.UrlLink.Replace("/app/labs/doctor-verify", $@"/new-lab-reports/{model.NewLabBookingDetailId}");
                var accountSessionPatientModel = await this.accountSessionServices.FetchDeviceTokenAsync(patientdetails.PatientId, Roles.Patient);
                var accountSessionModels = accountSessionPatientModel as AccountSessionModel[] ?? accountSessionPatientModel.ToArray();
                if (accountSessionModels.Any())
                {
                    var deviceTokenForProviderAndroid = accountSessionModels.Where(d => d.DeviceType == 2).Select(s => s.DeviceToken).ToList();
                    var deviceTokenForProviderIOS = accountSessionModels.Where(d => d.DeviceType == 3).Select(s => s.DeviceToken).ToList();
                    if (model.TestName != null)
                    {
                        if (deviceTokenForProviderAndroid.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                "Your Lab Report for " + model.TestName.ToUpper() + " is generated.",
                                "LabReport",
                                deviceTokenForProviderAndroid,
                                new List<string>(),
                                model.TestName,
                                DateTime.Now.ToString(),
                                null);
                        }

                        if (deviceTokenForProviderIOS.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                "Your Lab Report for " + model.TestName.ToUpper() + " is generated.",
                                "LabSampleRejected",
                                new List<string>(),
                                deviceTokenForProviderIOS,
                                model.TestName,
                                DateTime.Now.ToString(),
                                null);
                        }
                    }
                }
                    var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                    var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                    if ((bool)WhatsAppMessage[0].Active)
                    {
                        bool ret = await this.whatsAppSMSSender.SendLabReportWhatsAppMessage(patientdetails.Mobile, patientdetails.FullName, model.TestName, labLink);
                    }
                    
            }
            if (result > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.AccountId,
                    LabLogTypeId = (int)LabLogTypes.Lab_Doctor_Verified,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has  Verified <b>Lab Test</b> of <strong>{model.RequisitionNumber} - {model.TestName}</strong>.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return result;
        }

        /// <summary>
        /// Fetches the doctor signatures.
        /// </summary>
        /// <param name="newLabBookingDetailId">The new lab booking detail identifier.</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet]
        [Route("fetch-doctor-signatures")]
        public async Task<ActionResult> FetchDoctorSignatures(int newLabBookingDetailId)
        {
            var result = await this.labsService.FetchDoctorLabReportSignatureAsync(newLabBookingDetailId);
            return this.Success(result);
        }

        /// <summary>
        /// Fetches the doctors assigned.
        /// </summary>
        /// <param name="newLabBookingDetailId">The new lab booking detail identifier.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-doctors-assigned")]
        public async Task<ActionResult> FetchDoctorsAssigned(int newLabBookingDetailId)
        {
            var result = await this.labsService.FetchDoctorsAssignedForLabReportAsync(newLabBookingDetailId);
            return this.Success(result);
        }

        /// <summary>
        /// Fetches all machines.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-machines")]
        public async Task<ActionResult> FetchAllMachines()
        {
            return this.Success(await this.labsService.FetchAllMachines());
        }

        /// <summary>
        /// Uns the assigning doctor.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("remove-doctor")]
        public async Task<ActionResult> UnAssigningDoctor([FromBody] LabReportVerificationModel model)
        {
            var result = await this.labsService.DeletingDoctortoReports(model);
            return this.Success(result);
        }

        /// <summary>
        /// Fetches the patient labs.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-patient-labs")]
        public async Task<ActionResult> FetchPatientLabs([FromBody] LabReportPatientModel model, [FromHeader] LocationHeader header)
        {
            model = (LabReportPatientModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);
            if (!string.IsNullOrEmpty(model.EncryptedId))
            {
                model.PatientId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedId));
            }

            var responses = await this.labsService.FetchPatientLabsAsync(model);
            return this.Success(responses);
        }

        /// <summary>
        /// Fetches the patient labs.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("sample-collection-track-report")]
        public async Task<ActionResult> SampleCollectionTrackReport([FromBody] LabSampleHandlerModel model, [FromHeader] LocationHeader header)
        {
            model.LocationId = model.LocationId > 0 ? model.LocationId : !string.IsNullOrEmpty(header.LocationId) ? Convert.ToInt32(header.LocationId) : (int?)null;

            // model.LocationId = Convert.ToInt32(header.LocationId);
            var responses = await this.labsService.FetchSamplecollectiontrackreports(model);
            return this.Success(responses);
        }

        /// <summary>Fetchlabs the bookings.</summary>
        /// <param name="model">The model.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        [HttpPost]
        [Route("fetch-Lab-reports")]
        public async Task<ActionResult> FetchlabReports([FromBody] LabBookingModel model, [FromHeader] LocationHeader header)
        {
            model.LocationId = Convert.ToInt32(header.LocationId);
            model = (LabBookingModel)EmptyFilter.Handler(model);
            var responses = await this.labsService.FetchLabReports(model);
            foreach (var resource in responses)
            {
                resource.EncryptedId = this.aesHelper.Encode(resource.PatientId.ToString());
            }
            return this.Success(responses);
        }

        /// <summary>
        /// Fetches the labs parameter inputs check.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("get-parameter-allobservedvalues")]
        public async Task<ActionResult> FetchLabsParameterInputsCheck([FromBody] LabTransferModel model)
        {
            model = (LabTransferModel)EmptyFilter.Handler(model);
            var response = await this.labsService.FetchAllLabParameterObservedValuesAsync(model);
            var groupedList = new List<TempGroupClass>();
            foreach (var item in response)
            {
                var temp = new TempGroupClass
                {
                    ParameterName = item.ParameterName,
                    Params = new List<LabParameterResultsModel>()
                };
                temp.Params.Add(item);

                var checkIf = groupedList.Find(x => x.ParameterName == temp.ParameterName);
                if (checkIf != null)
                {
                    checkIf.Params.Add(item);
                }
                else
                {
                    groupedList.Add(temp);
                }
            }

            foreach (var data in groupedList)
            {
                for (int i = 0; i <= data.Params.Count - 2; i++)
                {
                    var toBeCompared = data.Params[i];
                    var toWithCompared = data.Params[i + 1];
                    if (toWithCompared.ObservedValue != toBeCompared.ObservedValue)
                    {
                        var checkInResponse = response.ToList().Find(x => x.LabParameterObservedValueId == toWithCompared.LabParameterObservedValueId);
                        checkInResponse.IsChanged = true;
                    }
                }
            }


            return this.Success(response);
        }

        /// <summary>
        /// Fetches the selected lab data web reports.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        [Route("fetch-selected-lab-data-webeports")]
        public async Task<ActionResult> FetchSelectedLabDataWebReports([FromBody] LabBookingModel model)
        {
            model = (LabBookingModel)EmptyFilter.Handler(model);
            var response = await this.labsService.FetchSelectedLabDataForWebReports(model);
            return this.Success(response);
        }

        /// <summary>
        /// Changes the sample process status.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("change-sampleprocess-status")]
        public async Task<ActionResult> ChangeSampleProcessStatus([FromBody] LabTransferModel model,[FromHeader] LocationHeader location)
        {
            model = (LabTransferModel)EmptyFilter.Handler(model);
            if (model.NewLabBookingDetailId == null) { return this.BadRequest("Invalid request"); }
            var response = await this.labsService.ChangeSampleProcessStatusAsync(model);

            if (model.Status == "SampleRejected" && response > 0)
            {
                var patientdetails = await this.resourceService.FetchPatientDetails((int)model.PatientId);
                var accountSessionPatientModel = await this.accountSessionServices.FetchDeviceTokenAsync(patientdetails.PatientId, Roles.Patient);
                var accountSessionModels = accountSessionPatientModel as AccountSessionModel[] ?? accountSessionPatientModel.ToArray();
                if (accountSessionModels.Any())
                {
                    var deviceTokenForProviderAndroid = accountSessionModels.Where(d => d.DeviceType == 2).Select(s => s.DeviceToken).ToList();
                    var deviceTokenForProviderIOS = accountSessionModels.Where(d => d.DeviceType == 3).Select(s => s.DeviceToken).ToList();
                    if (model.TestName != null)
                    {
                        if (deviceTokenForProviderAndroid.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                "Your Lab Sample for " + model.TestName.ToUpper() + " is Rejected.",
                                "LabSampleRejected",
                                deviceTokenForProviderAndroid,
                                new List<string>(),
                                model.TestName,
                                DateTime.Now.ToString(),
                                null);
                        }

                        if (deviceTokenForProviderIOS.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                "Your Lab Sample for " + model.TestName.ToUpper() + " is Rejected.",
                                "LabSampleRejected",
                                new List<string>(),
                                deviceTokenForProviderIOS,
                                model.TestName,
                                DateTime.Now.ToString(),
                                null);
                        }
                    }
                }
            }
            if (response > 0)
            {
                int LabLogTypeId = 0;
                switch (model.Status)
                {
                    case "SampleRejected":
                        LabLogTypeId = (int)LabLogTypes.Lab_Sample_Reject;
                        break;
                    case "SampleVerified":
                        LabLogTypeId = (int)LabLogTypes.Lab_Sample_Verified;
                        break;
                }
                var labLogModel = new LabLogModel
                {
                    AccountId = model.TransferedBy,
                    LabLogTypeId = LabLogTypeId,
                    LogFrom = (short)model.RoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $"{model.CreatedByName} has  {(model.Status == "SampleRejected" ? "Rejected" : "Accepted")} <b>Lab Samples</b> of <strong>{model.RequisitionNumber} - {model.TestName}</strong>.",
                    LocationId = Convert.ToInt32(location.LocationId)
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            return this.Success(response);
        }


        [HttpPost]
        [Route("fetch-parameter-added-labsonly")]
        public async Task<ActionResult> FetchSampleReceivedLabsAsync([FromBody] LabTransferModel model, [FromHeader] LocationHeader location)
        {
            model = (LabTransferModel)EmptyFilter.Handler(model);
            model.TransferedLocationId = Convert.ToInt32(location.LocationId);
            var responses = await this.labsService.FetchTransferedLabsAsync(model);
            return this.Success(responses);
        }

        [HttpPost]
        [Route("new-doctor-assigning")]
        public async Task<ActionResult> NewLabDoctorAssign([FromBody] NewDoctorAssigningModel model)
        {
            model = (NewDoctorAssigningModel)EmptyFilter.Handler(model);
            var result = await this.labsService.NewDoctorAssigning(model);
            return this.Success(result);
        }
        /// <summary>Fetchlabs the bookings.</summary>
        /// <param name="model">The model.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        [HttpPost]
        [Route("fetch-Lab-status-reports")]
        public async Task<ActionResult> FetchlabStatusReports([FromBody] LabBookingModel model, [FromHeader] LocationHeader header)
        {
            // model.LocationId = Convert.ToInt32(header.LocationId);
            model.LocationId = model.LocationId > 0 ? model.LocationId : !string.IsNullOrEmpty(header.LocationId) ? Convert.ToInt32(header.LocationId) : (int?)null;
            model = (LabBookingModel)EmptyFilter.Handler(model);

            var responses = await this.labsService.FetchLabStatusReports(model);

            return this.Success(responses);
        }

        [HttpPost]
        [Route("fetch-patient-past-lab-reports")]
        public async Task<ActionResult> FetchPatinetPastLabReports([FromBody] PatientPastLabReportsModel model)
        {
            var result = await this.labsService.FetchPatientPastLabReportsAsync(model);
            return this.Success(result);
        }


        [HttpGet]
        [Route("fetch-transfered-labs-number")]
        public async Task<ActionResult> FetchTransferedLabsForTransferNumber(int labTransferHeaderId)
        {
            var result = await this.labsService.FetchTransferedLabs(labTransferHeaderId);
            return this.Success(result);
        }

        [HttpPost]
        [Route("change-test-hold-status")]
        public async Task<ActionResult> ChangeHoldStatusOfTest([FromBody] LabHoldStatusModel model)
        {
            var result = await this.labsService.ChangeHoldStatusOfTest(model);
            return this.Success(result);
        }

        /// <summary>Fetchlabs the bookings.</summary>
        /// <param name="model">The model.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        [HttpPost]
        [Route("fetch-lab-tat-reports")]
        public async Task<ActionResult> FetchlabTatReports([FromBody] LabBookingModel model, [FromHeader] LocationHeader header)
        {
            model.LocationId = model.LocationId > 0 ? model.LocationId : !string.IsNullOrEmpty(header.LocationId) ? int.Parse(header.LocationId) : (int?)null;
            //  model.LocationId = Convert.ToInt32(header.LocationId);
            model = (LabBookingModel)EmptyFilter.Handler(model);

            var responses = await this.labsService.FetchLabTatReports(model);

            return this.Success(responses);
        }


        /// <summary>
        /// Modifies the lab vacutainer asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-lab-vacutainer")]
        public async Task<ActionResult> ModifyLabVacutainerAsync([FromBody] LabVacutainerModel model, [FromHeader] LocationHeader location)
        {
            model = (LabVacutainerModel)EmptyFilter.Handler(model);
            var response = await this.laboratoryVacutainerService.ModifyLabVacutainer(model);

            string message;
            switch (response)
            {
                case -1:
                case -2:
                    message = "The Lab Vacutainer name already exists";
                    break;
                case -3:
                    message = "Previous record not found for update";
                    break;
                case int n when n > 0:
                    var labLogModel = new LabLogModel
                    {
                        AccountId = model.CreatedBy,
                        LabLogTypeId = (int)LabLogTypes.LabDepartment,
                        LogFrom = model.RoleId > 0 ? (short)model.RoleId : short.Parse(1.ToString()),
                        LogDate = DateTime.UtcNow,
                        LocationId = int.Parse(location.LocationId),
                        LogDescription = $@"Lab Vacutainer : <b>{model.LabVacutainerName}</b> successfully {(model.LabVacutainerId > 0 ? "Updated" : "Added")} into Labs by {model.CreatedByName}"
                    };
                    await this.labLogService.LogAsync(labLogModel);
                    message = $@"Successfully {(model.LabVacutainerId > 0 ? "updated" : "created")}";
                    break;
                default:
                    message = "Error occured";
                    break;
            }

            return this.Success(message);
        }

        /// <summary>
        /// Fetches the lab vacutainers asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-lab-vacutainers")]
        public async Task<ActionResult> FetchLabVacutainersAsync([FromBody] LabVacutainerModel model)
        {
            model ??= new LabVacutainerModel();
            var response = await this.laboratoryVacutainerService.FetchAllVacutainerAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the lab vacutainers asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-lab-vacutainer-status")]
        public async Task<ActionResult> FetchLabVacutainersAsync([FromBody] LabVacutainerModel model, [FromHeader] LocationHeader location)
        {
            model = (LabVacutainerModel)EmptyFilter.Handler(model);
            var response = await this.laboratoryVacutainerService.ModifyLabVacutainerStatus(model);
            if (response > 0)
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.CreatedBy,
                    LabLogTypeId = (int)LabLogTypes.LabDepartment,
                    LogFrom = model.RoleId > 0 ? (short)model.RoleId : short.Parse(1.ToString()),
                    LogDate = DateTime.UtcNow,
                    LocationId = int.Parse(location.LocationId),
                    LogDescription = $@"Vacutainer : <b>{model.LabVacutainerName}</b> successfully {((bool)model.Active ? "Activated" : "Deactivated")} by {model.CreatedByName}"
                };
                await this.labLogService.LogAsync(labLogModel);
            }

            return this.Success(response);
        }
        /// <summary>
        /// The Multiple Lab Report Verification.
        /// </summary>
        /// <param name="model">the model.</param>
        /// <param name="location">the location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("multi-labreport-verification")]
        public async Task<ActionResult> MultipleLabReportVerification([FromBody] List<LabDoctorVerificationModel> model,[FromHeader]LocationHeader location)
        {
            int result = 0;

            foreach (var LabReport in model)
            {
                var count = await this.LabDoctorVerification(LabReport, location);
                if (count > 0)
                {
                    result++;
                }
            }
            if (model.Count() == result)
            {
                return this.Success(result);
            }
            else
            {
                return this.Success(-10);
            }


        }

        /// <summary>
        /// Fetches the mobile booked labs.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-labs-mobile-Booked")]
        public async Task<ActionResult> FetchMobileBookedLabs([FromBody] ApointmentLabsMobileModel model)
        {
            model = (ApointmentLabsMobileModel)EmptyFilter.Handler(model);
            var response = await this.labsService.FetchAppointmentMobileLabsAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the external lab agencies asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-external-lab-agency")]
        public async Task<ActionResult> FetchExternalLabAgenciesAsync([FromBody] ExternalLabAgencyModel model)
        {
            model ??= new ExternalLabAgencyModel();
            var response = await this.labsService.FetchExternalLabAgencyAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the external lab agency details asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-external-lab-agency-detail")]
        public async Task<ActionResult> FetchExternalLabAgencyDetailsAsync([FromBody] ExternalLabAgencyModel model)
        {
            model ??= new ExternalLabAgencyModel();
            var response = await this.labsService.FetchExternalLabAgencyDetailsAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the external lab agency status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-external-lab-agency-status")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> ModifyExternalLabAgencyStatusAsync([FromBody] ExternalLabAgencyModel model, [FromHeader] LocationHeader location)
        {
            model = (ExternalLabAgencyModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ActivateOrDeactivateExternalLabAgency(model);
            if (response == 0)
            {
                return this.ServerError();
            }
            var labLogModel = new LabLogModel
            {
                AccountId = model.CreatedBy,
                LabLogTypeId = (int)LabLogTypes.Lab_Masters_Agency,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = $" {model.CreatedByName} has changed status of <b>Agency</b> - <strong>{model.AgencyName}</strong> on {DateTime.Now}",
                LocationId = Convert.ToInt32(location.LocationId)
            };
            await this.labLogService.LogAsync(labLogModel);



            return this.Success("Agency status has been modified  successfully.");

        }

        /// <summary>
        /// Modifies the external lab agency detail status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-external-lab-agency-detail-status")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> ModifyExternalLabAgencyDetailStatusAsync([FromBody] ExternalLabAgencyDetailModel model, [FromHeader] LocationHeader location)
        {
            model = (ExternalLabAgencyDetailModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ActivateOrDeactivateExternalLabAgencyDetail(model);
            if (response == 0)
            {
                return this.ServerError();
            }
            return this.Success("Agency status has been modified  successfully.");

        }

        /// <summary>
        /// Modifies the external lab agency asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-external-lab-agency")]
        public async Task<ActionResult> ModifyExternalLabAgencyAsync([FromBody] ExternalLabAgencyModel model, [FromHeader] LocationHeader location)
        {
            model = (ExternalLabAgencyModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ModifyExternalLabAgency(model);

            string message;
            switch (response)
            {
                case -1:
                case -2:
                    message = "The Agency name already exists";
                    break;
                case -3:
                    message = "Previous record not found for update";
                    break;
                case int n when n > 0:
                    var labLogModel = new LabLogModel
                    {
                        AccountId = model.CreatedBy,
                        LabLogTypeId = (int)LabLogTypes.Lab_Masters_Agency,
                        LogFrom = model.LoginRoleId > 0 ? (short)model.LoginRoleId : short.Parse(1.ToString()),
                        LogDate = DateTime.UtcNow,
                        LocationId = int.Parse(location.LocationId),
                        LogDescription = $@"Lab Agency : <b>{model.AgencyName}</b> successfully {(model.ExternalLabAgencyId > 0 ? "Updated" : "Added")} into Labs by {model.CreatedByName}"
                    };
                    await this.labLogService.LogAsync(labLogModel);
                    message = $@"Successfully {(model.ExternalLabAgencyId > 0 ? "updated" : "created")}";
                    break;
                default:
                    message = "Error occured";
                    break;
            }

            return this.Success(message);
        }

        /// <summary>
        /// Modifies the external lab agency detail asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-external-lab-agency-detail")]
        public async Task<ActionResult> ModifyExternalLabAgencyDetailAsync([FromBody] ExternalLabAgencyModel model, [FromHeader] LocationHeader location)
        {
            model = (ExternalLabAgencyModel)EmptyFilter.Handler(model);
            var response = await this.labsService.ModifyExternalLabAgency(model);
            if (response > 0)
            {
                 response = await this.labsService.ModifyExternalLabAgencyDetail(model.Labs);
            }
            string message;
            switch (response)
            {
                case -1:
                case -2:
                    message = "The Agency name already exists";
                    break;
                case -3:
                    message = "Previous record not found for update";
                    break;
                case -4:
                    message = "The issue in New Records";
                    break;
                case -5:
                    message = "Previous record not able to update";
                    break;
                case int n when n > 0:
                    var labLogModel = new LabLogModel
                    {
                        AccountId = model.Labs[0].CreatedBy,
                        LabLogTypeId = (int)LabLogTypes.Lab_Masters_Agency,
                        LogFrom = model.LoginRoleId > 0 ? (short)model.LoginRoleId : short.Parse(1.ToString()),
                        LogDate = DateTime.UtcNow,
                        LocationId = int.Parse(location.LocationId),
                        LogDescription = $@"Lab Agency : <b>{model.AgencyName}</b> successfully {(model.ExternalLabAgencyId > 0 ? "Updated" : "Added")}  Labs by {model.CreatedByName} "
                    };
                    await this.labLogService.LogAsync(labLogModel);
                    message = $@"Successfully {(model.ExternalLabAgencyId > 0 ? "updated" : "Added")}";
                    break;
                default:
                    message = "Error occured";
                    break;
            }

            return this.Success(message);
        }

        /// <summary>
        /// Fetches the lab with charge category charge asynchronous.
        /// </summary>
        /// <param name="term">The term.</param>
        /// <param name="chargeCategoryId">The charge category identifier.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-lab-chargecategory-charge")]
        public async Task<ActionResult> FetchLabWithChargeCategoryChargeAsync(string term, int chargeCategoryId, [FromHeader] LocationHeader location)
        {

            //need charge Category Id and If un want U can send term also.
            var model = new LabChargeCategoryChargeModel();
            model.Term = term;
            model.ChargeCategoryId = chargeCategoryId;
            model.LocationId = Convert.ToInt32(location.LocationId);
            var getModulesData = await this.chargeModuleService.GetRequiredDetailForChargeFetchAsync("lab", (int)model.LocationId);
            if (getModulesData == null)
            {
                return this.Success(new List<LabChargeCategoryChargeModel>());
            }
            else
            {
                model.ChargeModuleTemplateId = (int)getModulesData.ChargeModuleTemplateId;
                model.ModulesMasterId = (int)getModulesData.ModulesMasterId;
            }
            var response = await this.labsService.FetchLabWithChargeCategoryChargeAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the sample collected labs asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-sample-collected-tests")]
        public async Task<ActionResult> FetchSampleCollectedLabsAsync([FromBody] NewLabSampleHandlerModel model)
        {
            model = (NewLabSampleHandlerModel)EmptyFilter.Handler(model);
            //model.LocationId = Convert.ToInt32(header.LocationId);
            var response = await this.labsService.FetchSampleCollectedAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Uns the collect samples asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("uncollect-samples")]
        public async Task<ActionResult> UnCollectSamplesAsync([FromBody] List<LabSampleHandlerModel> model, [FromHeader] LocationHeader location)
        {
            model = (List<LabSampleHandlerModel>)EmptyFilter.Handler(model);
            int locationId = Convert.ToInt32(location.LocationId);
            var response = await this.labsService.UnCollectSamplesAsync(model, locationId);
            return this.Success(response);
        }

        [HttpGet]
        [Route("get-all-sample-uncollect-reasons")]
        public async Task<ActionResult> GetAllSampleUncollectReasons()
        {
            var responce = await this.labsService.GetAllSampleUncollectReasons();
            return this.Success(responce);
        }

        [HttpGet]
        [Route("get-all-sample-reject-reasons")]
        public async Task<ActionResult> GetAllSampleRejectReasons()
        {
            var responce = await this.labsService.GetAllSampleRejectReasons();
            return this.Success(responce);
        }

        /// <summary>
        /// Checks the external lab agency tagged or not.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("check-external-agency-exists")]
        public async Task<ActionResult> CheckExternalLabAgencyTaggedOrNot([FromBody] ExternalLabAgencyDetailModel model)
        {
            model = (ExternalLabAgencyDetailModel)EmptyFilter.Handler(model);
            var response = await this.labsService.CheckLabIsTaggedOrNotAsync(model);
            return this.Success(response);
        }

        [HttpGet]
        [Route("fetch-test-params-lis")]
        public async Task<ActionResult> FetchLabParmsForLISAsync(int newLabBookingDetailId)
        {

            
            var response = await this.labsService.FetchTestParamsForLISAsync(newLabBookingDetailId);
            return this.Success(response);
        }

        [HttpGet]
        [Route("insert-test-params-lis")]
        public async Task<ActionResult> InsertLabParamsofLISAsync([FromBody] List<LISParamsFetchUserModel> model)
        {

            model = (List<LISParamsFetchUserModel>)EmptyFilter.Handler(model);
            var response = await this.labsService.InsertTestParamsOfLISAsync(model);
            return this.Success(response);
        }
    }

    public class TempGroupClass
    {
        public string ParameterName { get; set; }
        public List<LabParameterResultsModel> Params { get; set; }
    }

}