namespace Hims.Api.Controllers
{
    using Domain.Helpers;
    using Domain.Services;
    using Hims.Api.Senders;
    using Hims.Domain.Configurations;
    using Hims.Shared.Library.Enums;
    using Hims.Shared.UserModels.Common;
    using Hims.Shared.UserModels.Filters;
    using Hims.Shared.UserModels.Pharmacy;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Shared.DataFilters;
    using Shared.EntityModels;
    using Shared.UserModels;
    using Shared.UserModels.PharmacyRequest;
    using Shared.UserModels.OperationTheater;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Utilities;
    using Hims.Api.Models;
    using Newtonsoft.Json;

    /// <summary>
    /// The pharmacy controller.
    /// </summary>
    [Authorize]
    [Route("api/pharmacy")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class PharmacyController : BaseController
    {
        /// <summary>
        /// The pharmacy service.
        /// </summary>
        private readonly IPharmacyService pharmacyService;

        /// <summary>
        /// The pharmacy service.
        /// </summary>
        private readonly IResourceService resourceService;

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

        /// <summary>
        /// The pharmacy service.
        /// </summary>
        private readonly IPharmacyLogService pharmacyLogService;

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

        /// <summary>
        /// The company service.
        /// </summary>
        private readonly ICompanyService companyService;

        /// <summary>
        /// The email sender.
        /// </summary>
        private readonly IEmailSender emailSender;
        /// <summary>
        /// The running environment.
        /// </summary>
        private readonly IRunningEnvironment runningEnvironment;

        /// <summary>
        /// The notification service.
        /// </summary>
        private readonly IWebNotificationService notificationService;

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

        /// <summary>
        /// The patient services.
        /// </summary>
        private readonly IPatientService patientService;
        
        /// <summary>
        /// The setting service
        /// </summary>
        private readonly ISettingService settingService;

        /// <inheritdoc />
        public PharmacyController(IPharmacyService pharmacyService, IResourceService resourceService, IAESHelper aesHelper, IPharmacyLogService pharmacyLogService, ILabLogService labLogService, ICompanyService companyService, IEmailSender emailSender, IRunningEnvironment runningEnvironment, IWebNotificationService webNotificationService, IWhatsAppSMSSender whatsAppSMSSender, IPatientService patientService, ISettingService settingService)
        {
            this.pharmacyService = pharmacyService;
            this.resourceService = resourceService;
            this.aesHelper = aesHelper;
            this.pharmacyLogService = pharmacyLogService;
            this.labLogService = labLogService;
            this.companyService = companyService;
            this.emailSender = emailSender;
            this.runningEnvironment = runningEnvironment;
            this.notificationService = webNotificationService;
            this.whatsAppSMSSender = whatsAppSMSSender;
            this.patientService = patientService;
            this.settingService = settingService;    
        }

        /// <summary>
        /// The insert common pharmacy masters async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("create-common-masters")]
        public async Task<ActionResult> InsertCommonPharmacyMastersAsync([FromBody] LookupValueModel model)
        {
            model = (LookupValueModel)EmptyFilter.Handler(model);
            int response;
            int pharmacyLogTypeId;
            string logDescription;
            switch (model.TypeOf)
            {
                case "Gst":
                    response = await this.pharmacyService.CreateGstAsync(model);
                    pharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_GST;
                    logDescription = $@"New GST '{model.Name}%' Added Successfully.";
                    break;
                case "Unit":
                    response = await this.pharmacyService.CreateUnitAsync(model);
                    pharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_Units;
                    logDescription = $@"New Unit '{model.Name}' Added Successfully.";
                    break;
                case "Category":
                    response = await this.pharmacyService.CreateCategoryAsync(model);
                    pharmacyLogTypeId = (int)PharmacyLogTypes.Category;
                    logDescription = $@"New Category '{model.Name}' Added Successfully.";
                    break;
                case "Rack":
                    response = await this.pharmacyService.CreateRackAsync(model);
                    pharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_Rack;
                    logDescription = $@"New Rack '{model.Name}' Added Successfully.";
                    break;
                default:
                    response = await this.pharmacyService.CreateLookupValueAsync(model);
                    return this.Success(response);

            }
            if (response < 0)
            {
                return this.BadRequest("The given value already exists.");
            }
            if (response > 0)
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.LoginAccountId,
                    PharmacyLogTypeId = pharmacyLogTypeId,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = logDescription
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            }

            return this.Success(response);
        }

        /// <summary>
        /// The fetch lookup value async.
        /// </summary>
        /// <param name="model">
        /// The name.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("fetch-lookup-value")]
        public async Task<ActionResult> FetchLookupValueAsync(LookupValueModel model)
        {
            model = (LookupValueModel)EmptyFilter.Handler(model);
            if (string.IsNullOrEmpty(model.Name))
            {
                return this.BadRequest("Invalid name.");
            }

            var response = await this.pharmacyService.FetchLookupValues(model);
            return this.Success(response);
        }

        /// <summary>
        /// The Get All UnitTypes
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("get-all-units")]
        public async Task<ActionResult> GetAllUnitTypes()
        {
            var responce = await this.pharmacyService.GetAllUnitTypes();
            return this.Success(responce);
        }

        /// <summary>
        /// The update lookup value async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("update-lookup-value")]
        public async Task<ActionResult> UpdateLookupValueAsync([FromBody] LookupValueModel model, [FromHeader] LocationHeader header)
        {
            model = (LookupValueModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);          
            var response = await this.pharmacyService.UpdateLookupValueAsync(model);
                     
            if (response < 0)
            {
                return this.BadRequest("The given value already exists.");
            }

            switch (model.TypeOf)
            {
                case "Gst":
                    model.PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_GST;
                    model.LogDescription = $@"GST Updated to '{model.Name}%' Successfully.";
                    break;
                case "Unit":
                    if (model.TypeName == "PharmacyUnit")
                    {
                        model.PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_Units;
                        model.LogDescription = $@"Unit Updated to '{model.Name}' Successfully.";
                    }
                    if (model.TypeName == "LaboratoryUnit")
                    {
                        model.LabLogTypeId = (int)LabLogTypes.Lab_Masters_Unit;
                        model.LogDescription = $@"'{model.AccountFullName}' has Updated Unit to  '{model.Name}'";
                    }
                    break;
                case "Category":
                    model.PharmacyLogTypeId = (int)PharmacyLogTypes.Category;
                    model.LogDescription = $@"Category Updated to '{model.Name}' Successfully.";
                    break;
                case "Rack":
                    model.PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_Rack;
                    model.LogDescription = $@"Rack Updated to '{model.Name}' Successfully.";
                    break;
                default:
                    return this.Success(response);
            }
            if (model.TypeName == "PharmacyUnit")
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.LoginAccountId,
                    PharmacyLogTypeId = model.PharmacyLogTypeId,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = model.LogDescription
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            }
            if (model.TypeName == "LaboratoryUnit")
            {
                var labLogModel = new LabLogModel
                {
                    AccountId = model.LoginAccountId,
                    LabLogTypeId = model.LabLogTypeId,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = model.LogDescription,
                    LocationId = (int)model.LocationId
                };
                await this.labLogService.LogAsync(labLogModel);
            }
            if (response>0)
            {
               
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.LoginAccountId,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.Category,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.UtcNow.AddMinutes(330),
                    LogDescription =  $@"<b>{model.ModifiedByName}</b> {(model.LookupValueId > 0 ? "updated" : "added")} the Category <b>{model.Name}</b> on {DateTime.UtcNow.AddMinutes(330).ToString("MM/dd/yyyy, hh:mm tt")} successfully",
                    LocationId = Convert.ToInt32(header.LocationId)
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            }
            return this.Success(response);
        }

        /// <summary>
        /// The delete lookup value async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("delete-lookup-value")]
        public async Task<ActionResult> DeleteLookupValueAsync([FromBody] LookupValueModel model, [FromHeader] LocationHeader header)
        {
            model = (LookupValueModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);
            try
            {
                var response = await this.pharmacyService.DeleteLookupValueAsync(model.LookupValueId);
                if (response>0)
                {
                    var pharmacyLogModel = new PharmacyLogModel
                    {
                        AccountId = model.LoginAccountId,
                        PharmacyLogTypeId = (int)PharmacyLogTypes.Category,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LogDescription = $@"<b> {model.ModifiedByName}</b> has deleted Category - <b>{model.Name}</b> on {DateTime.UtcNow.AddMinutes(330).ToString("MM/dd/yyyy, hh:mm tt")} successfully",
                        LocationId = Convert.ToInt32(header.LocationId)
                    };
                    await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                }           
                switch (model.TypeOf)
                {
                    case "Gst":
                        model.PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_GST;
                        model.LogDescription = $@"GST '{model.Name}%' Deleted Successfully.";
                        break;
                    case "Unit":
                        if (model.TypeName == "PharmacyUnit")
                        {
                            model.PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_Units;
                            model.LogDescription = $@"Unit Deleted '{model.Name}' Successfully.";
                        }
                        if (model.TypeName == "LaboratoryUnit")
                        {
                            model.LabLogTypeId = (int)LabLogTypes.Lab_Masters_Unit;
                            model.LogDescription = $@"'{model.AccountFullName}' has Deleted Unit '{model.Name}'";
                        }
                        break;
                    case "Category":
                        model.PharmacyLogTypeId = (int)PharmacyLogTypes.Category;
                        model.LogDescription = $@"Category '{model.Name}' Deleted Successfully.";
                        break;
                    case "Rack":
                        model.PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_Rack;
                        model.LogDescription = $@"Rack '{model.Name}' Deleted Successfully.";
                        break;
                    default:
                        return this.Success(new GenericResponse
                        {
                            Status = response > 0 ? GenericStatus.Success : GenericStatus.Warning
                        });
                }
                if (model.TypeName == "PharmacyUnit")
                {
                    var pharmacyLogModel = new PharmacyLogModel
                    {
                        AccountId = model.LoginAccountId,
                        PharmacyLogTypeId = model.PharmacyLogTypeId,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.Now,
                        LogDescription = model.LogDescription
                    };
                    await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                }
                if (model.TypeName == "LaboratoryUnit")
                {
                    var labLogModel = new LabLogModel
                    {
                        AccountId = model.LoginAccountId,
                        LabLogTypeId = model.LabLogTypeId,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.Now,
                        LogDescription = model.LogDescription,
                        LocationId = (int)model.LocationId

                    };
                    await this.labLogService.LogAsync(labLogModel);
                }
                return this.Success(new GenericResponse
                {
                    Status = response > 0 ? GenericStatus.Success : GenericStatus.Warning
                });
            }
            catch (Exception ex)
            {
                if (model.TypeName == "PharmacyUnit" && model.TypeOf == "Unit" && ex.Message.Contains("update or delete on table \"LookupValue\" violates foreign key constraint \"PharmacyProduct_PurchaseUnit_fkey\" on table \"PharmacyProduct\""))
                {
                    return this.Success(new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = ex.Message
                    });
                }
                if (model.TypeOf == "Gst" && ex.Message.Contains("update or delete on table \"LookupValue\" violates foreign key constraint \"PharmacyProduct_TaxId_fkey\" on table \"PharmacyProduct\""))
                {
                    return this.Success(new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = ex.Message
                    });
                }

                if (model.TypeOf == "Category" && ex.Message.Contains("update or delete on table \"LookupValue\" violates foreign key constraint \"PharmacyProduct_CategoryId_fkey\" on table \"PharmacyProduct\""))
                {
                    return this.Success(new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = ex.Message
                    });
                }
                if (model.TypeOf == "Rack" && ex.Message.Contains("update or delete on table \"LookupValue\" violates foreign key constraint \"PharmacyProduct_RackId_fkey\" on table \"PharmacyProduct\""))
                {
                    return this.Success(new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = ex.Message
                    });
                }
                if (model.TypeName == "LaboratoryUnit" && model.TypeOf == "Unit" && ex.Message.Contains("update or delete on table \"LookupValue\" violates foreign key constraint \"LabDetail_RefrenceRangeUnit_fkey\" on table \"LabDetail\""))
                {
                    return this.Success(new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = ex.Message
                    });
                }
                if (model.TypeName == "LaboratoryUnit" && model.TypeOf == "Unit" && ex.Message.Contains("update or delete on table \"LookupValue\" violates foreign key constraint \"LabParameterDetail_UnitId_fkey\" on table \"LabParameterDetail\""))
                {
                    return this.Success(new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = ex.Message
                    });
                }
                throw;
            }
        }

        /// <summary>
        /// The add pharmacy product.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("add-product")]
        public async Task<ActionResult> AddPharmacyProduct([FromBody] ProductModel model)
        {
            model = (ProductModel)EmptyFilter.Handler(model);
            var requestModel = await this.CheckProducts(model);
            var response = await this.pharmacyService.CreatePharmacyProduct(requestModel);

            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.LoginAccountId,
                PharmacyLogTypeId = (int)PharmacyLogTypes.Product,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = $@" <b>{model.CreatedByName}</b> has Added New Product '{model.ProductName}' Successfully."
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            return this.Success(response);
        }

        /// <summary>
        /// The fetch pharmacy product.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-product")]
        public async Task<ActionResult> FetchPharmacyProduct([FromBody] ProductModel model)
        {
            var models = model ?? new ProductModel();
            var response = await this.pharmacyService.FetchPharmacyProduct(models);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the pharmacy products.
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-products")]
        public async Task<ActionResult> FetchPharmacyProducts()
        {
            var response = await this.pharmacyService.FetchPharmacyProducts();
            return this.Success(response);
        }

        /// <summary>
        /// The add pharmacy product.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("update-product")]
        public async Task<ActionResult> UpdatePharmacyProduct([FromBody] ProductModel model)
        {
            model = (ProductModel)EmptyFilter.Handler(model);
            var requestModel = await this.CheckProducts(model);
            var response = await this.pharmacyService.UpdatePharmacyProduct(requestModel);

            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.LoginAccountId,
                PharmacyLogTypeId = (int)PharmacyLogTypes.Product,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = $@" <b>{model.CreatedByName}</b> has Updated Product '{model.ProductName}' Details Successfully."
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            return this.Success(response);
        }

        /// <summary>
        /// The delete pharmacy product.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("delete-product")]
        public async Task<ActionResult> DeletePharmacyProduct([FromBody] ProductModel model)
        {
            model = (ProductModel)EmptyFilter.Handler(model);
            try
            {
                var response = await this.pharmacyService.DeletePharmacyProduct(model.PharmacyProductId);

                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.LoginAccountId,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.Product,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $@"Product '{model.ProductName}' Deleted Successfully."
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                return this.Success(new GenericResponse
                {
                    Status = response > 0 ? GenericStatus.Success : GenericStatus.Warning
                });
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("update or delete on table \"PharmacyProduct\" violates foreign key constraint \"PharmacyPurchaseDetail_PharmacyProductId_fkey\" on table \"PharmacyPurchaseDetail\""))
                {
                    return this.Success(new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = ex.Message
                    });
                }
                throw;
            }
        }

        /// <summary>
        /// The fetch return bill number async.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("fetch-auto-bill-number")]
        public async Task<ActionResult> FetchReturnBillNumberAsync()
        {
            var response = await this.pharmacyService.FetchBillNumber();
            return this.Success(response);
        }

        /// <summary>
        /// The fetch pharmacy purchase bill.
        /// </summary>
        /// <param name="pharmacyPurchaseHeaderId"></param>
        /// <param name="type">
        /// The type.
        /// </param>       
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("fetch-Pharmacy-Purchase-bill")]
        public async Task<ActionResult> FetchPharmacyPurchaseBill(string pharmacyPurchaseHeaderId, string type)
        {
            if (string.IsNullOrEmpty(pharmacyPurchaseHeaderId))
            {
                return this.BadRequest();
            }

            var response = await this.pharmacyService.FetchPharmacyPurchaseBill(int.Parse(pharmacyPurchaseHeaderId), type);

            foreach (var stock in response)
            {
                stock.EncryptedPharmacyStockId = this.aesHelper.Encode(stock.PharmacyStockId.ToString());
            }

            return this.Success(response);
        }

        /// <summary>
        /// The fetch added purchase bill async.
        /// </summary>
        /// <param name="pharmacyHeaderId">
        /// The pharmacy header id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("fetch-added-purchase-bill")]
        public async Task<ActionResult> FetchAddedPurchaseBillAsync(string pharmacyHeaderId)
        {
            if (string.IsNullOrEmpty(pharmacyHeaderId))
            {
                return this.BadRequest();
            }

            var response = await this.pharmacyService.FetchAddedBill(int.Parse(pharmacyHeaderId));
            return this.Success(response);
        }

        /// <summary>
        /// The fetch added purchase bill async.
        /// </summary>
        /// <param name="billNumber">
        /// The bill number.
        /// </param>
        /// <param name="supplierId">
        /// The supplier id.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Authorize]
        [Route("fetch-added-purchase-bill-by-supplierId")]
        public async Task<ActionResult> FetchAddedPurchaseBillAsync(string billNumber, string supplierId, [FromHeader] LocationHeader header)
        {
            if (string.IsNullOrEmpty(supplierId) && string.IsNullOrEmpty(billNumber))
            {
                return this.BadRequest();
            }
            var locationId = header != null ? int.Parse(header.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchPurchaseBill(int.Parse(supplierId), billNumber, locationId);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch pharmacy stock async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-pharmacy-stock")]
        public async Task<ActionResult> FetchPharmacyStockAsync([FromBody] PharmacyStockModel model)
        {
            var models = model ?? new PharmacyStockModel();
            var response = await this.pharmacyService.FetchPharmacyStocks(models);
            foreach (var stock in response)
            {
                stock.EncryptedPharmacyStockId = this.aesHelper.Encode(stock.PharmacyStockId.ToString());
            }

            return this.Success(response);
        }

        /// <summary>
        /// The fetch pharmacy retail stock async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-pharmacy-retail-stock")]
        public async Task<ActionResult> FetchPharmacyRetailStockAsync([FromBody] PharmacyStockModel model)
        {
            var models = model ?? new PharmacyStockModel();
            var response = await this.pharmacyService.FetchPharmacyRetailStocks(models);
            return this.Success(response);
        }

        /// <summary>
        /// The add pharmacy sale bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("add-sales-bill")]
        public async Task<ActionResult> AddPharmacySaleBillAsync([FromBody] PharmacySaleBillModel model)
        {
            model = (PharmacySaleBillModel)EmptyFilter.Handler(model);

            var (response, t) = model.PharmacySaleHeaderId > 0 ? await this.pharmacyService.UpdateSaleBill(model) : await this.pharmacyService.AddSaleBill(model);

            var productModel = new ProductModel
            {
                PharmacyProductId = model.PharmacyProductId
            };
            var pharmacyProduct = (await this.pharmacyService.FetchPharmacyProduct(productModel)).ToList();

            if (response > 0)
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.LoginAccountId,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Sales,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = model.PharmacySaleHeaderId > 0 ? $@"Sales Bill Updated Successfully<br/>Bill Number:'{model.BillNumber}'<br/>Patient Name:'{model.PatientName}'<br/>Medicine Type:'Medicine'<br/>Product Name:'{pharmacyProduct[0].ProductName}'<br/>Quantity:'{model.Quantity}'" : $@"New Sales Bill Added Successfully<br/>Bill Number:'{t}'<br/>Patient Name:'{model.PatientName}'<br/>Type:'Medicine'<br/>Product Name:'{pharmacyProduct[0].ProductName}<br/>Quantity:'{model.Quantity}'"
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            }

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

        /// <summary>
        /// The fetch added sales bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="location"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("fetch-added-sales-bill")]
        public async Task<ActionResult> FetchAddedSalesBillAsync([FromBody] PharmacySaleBill model, [FromHeader] LocationHeader location)
        {
            model = (PharmacySaleBill)EmptyFilter.Handler(model);
            var locationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchSaleAddedBill(model.PharmacySaleHeaderId, model.BillNumber, locationId);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch added sales return bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-added-sales-return-bill")]
        public async Task<ActionResult> FetchAddedSalesReturnBillAsync([FromBody] PharmacySaleBill model)
        {
            model = (PharmacySaleBill)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchSaleReturnDetialsBill(model.PharmacySaleHeaderId, model.BillNumber, model.SaleReturnHeaderId);
            return this.Success(response);
        }

        /// <summary>
        /// The add surgery kit async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("add-surgery-kit")]
        public async Task<ActionResult> AddSurgeryKitAsync([FromBody] SurgeryHeaderModel model)
        {
            model = (SurgeryHeaderModel)EmptyFilter.Handler(model);
            var response = model.SurgeryKitHeaderId > 0 ? await this.pharmacyService.UpdateSurgeryKit(model) : await this.pharmacyService.AddSurgeryKit(model);

            if (response > 0)
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.LoginAccountId,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_SurgeryKit,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = model.SurgeryKitHeaderId > 0 ? $@"Surgery Kit '{model.KitName}' Details Updated Successfully." : $@"New Surgery Kit '{model.KitName}' Added Successfully."
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            }
            if (response == -1)
            {
                return this.Success(-1);
            }
            return response > 0 ? this.Success(response) : this.ServerError();
        }

        /// <summary>
        /// The fetch surgery header.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("fetch-surgery-kit")]
        public async Task<ActionResult> FetchSurgeryHeader()
        {
            var response = await this.pharmacyService.FetchSurgeryKitHeaders();
            return this.Success(response);
        }

        /// <summary>
        /// The fetch surgery header.
        /// </summary>
        /// <param name="id">
        /// The id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("fetch-surgery-detail")]
        public async Task<ActionResult> FetchSurgeryHeader(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return this.BadRequest();
            }

            var response = await this.pharmacyService.FetchSurgeryDetails(Convert.ToInt32(id));
            return this.Success(response);
        }

        /// <summary>
        /// The delete surgery kit async.
        /// </summary>
        /// <param name="id">
        /// The id.
        /// </param>
        /// <param name="LoginAccountId"></param>
        /// <param name="LoginRoleId"></param>
        /// <param name="KitName"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("delete-surgery-kit")]
        public async Task<ActionResult> DeleteSurgeryKitAsync(string id, int LoginAccountId, int LoginRoleId, string KitName)
        {
            if (string.IsNullOrEmpty(id))
            {
                return this.BadRequest();
            }

            var response = await this.pharmacyService.DeleteSurgeryKit(Convert.ToInt32(id));

            if (response > 0)
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = LoginAccountId,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_SurgeryKit,
                    LogFrom = (short)LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $@"Surgery Kit '{KitName}' Deleted Successfully."
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            }

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

        /// <summary>
        /// The fetch dashboard product expiring next month.
        /// </summary>
        ///<param name="location"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("dashboard-expiring-next-month")]
        public async Task<ActionResult> FetchDashboardProductExpiringNextMonth([FromHeader] LocationHeader location)
        {
            var locationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchProductExpiryNextMonth(locationId);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch dashboard product expiring next months.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-next-expiring-products")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyDashboardModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchProductExpiringInNextMonths([FromBody] PharmacyReportFilterModel model, [FromHeader] LocationHeader location)
        {
            model = (PharmacyReportFilterModel)EmptyFilter.Handler(model);
            model.LocationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchProductExpiryInNextMonths(model);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch dashboard product expiring this month.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("dashboard-expiring-this-month")]
        public async Task<ActionResult> FetchDashboardProductExpiringThisMonth([FromHeader] LocationHeader location)
        {
            var locationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchProductExpiryThisMonth(locationId);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the dashboard product under reorder level.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("dashboard-product-under-reorder")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyDashboardModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchDashboardProductUnderReorderLevel([FromBody] PharmacyReportFilterModel model, [FromHeader] LocationHeader location)
        {
            model = (PharmacyReportFilterModel)EmptyFilter.Handler(model);
            model.LocationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchProductUnderReorderLevel(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the dashboard product expiring next month retail.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("dashboard-expiring-next-month-retail")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyDashboardModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchDashboardProductExpiringNextMonthRetail([FromBody] PharmacyReportFilterModel model, [FromHeader] LocationHeader location)
        {
            model = (PharmacyReportFilterModel)EmptyFilter.Handler(model);
            model.LocationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchProductExpiryNextMonthRetail(model);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch dashboard product expiring this month.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("dashboard-expiring-this-month-retail")]
        public async Task<ActionResult> FetchDashboardProductExpiringThisMonthRetail([FromHeader] LocationHeader location)
        {
            var locationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchProductExpiryThisMonthRetail(locationId);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the dashboard product under reorder level retail.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("dashboard-product-under-reorder-retail")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyDashboardModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchDashboardProductUnderReorderLevelRetail([FromBody] PharmacyReportFilterModel model, [FromHeader] LocationHeader location)
        {
            model = (PharmacyReportFilterModel)EmptyFilter.Handler(model);
            model.LocationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchProductUnderReorderLevelRetail(model);
            return this.Success(response);
        }

        /// <summary>
        /// The add sales return bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("add-pharmacy-sale-return-bill")]
        [Consumes("multipart/form-data")]
        public async Task<ActionResult> AddSalesReturnBillAsync([FromForm] PharmacySaleReturnBillModel model)
        {
            var response = await this.ReturnAsyncHelper(model);

            if (response > 0)
            {
                var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                if ((bool)WhatsAppMessage[0].Active)
                {
                    _ = this.whatsAppSMSSender.SendPharmacyWhatsAppMessage(model.PatientMobile, model.PatientName, "PharmacyReturn");
                }
                return this.Success(new GenericResponse
                {
                    Status = GenericStatus.Success,
                    Data = response
                });
            }
            else
            {
                return this.ServerError();
            }
        }

        /// <summary>
        /// Adds the asynchronous helper.
        /// </summary>
        /// <param name="model">The model.</param>\
        /// <returns></returns>
        public async Task<int> ReturnAsyncHelper(PharmacySaleReturnBillModel model)
        {
            model = (PharmacySaleReturnBillModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.AddPharmacySaleBillReturnAsync(model);

            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.LoginAccountId,
                PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Sales_Return,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = $@"Pharmacy Sales Return Bill Added Successfully.<br/>Bill Number:'{model.BillNumber}'<br/>Return Quantity:'{model.Quantity}'"
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            return response;
        }

        /// <summary>
        /// The fetch sales return bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("get-sale-return-bill")]
        public async Task<ActionResult> FetchSalesReturnBillAsync([FromBody] PharmacySaleReturnBillModel model)
        {
            model = (PharmacySaleReturnBillModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchSaleReturnBill(model.SaleReturnHeaderId, model.BillNumber);
            return this.Success(response);
        }

        /// <summary>
        /// The add retail stock async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("add-retail-stock")]
        public async Task<ActionResult> AddRetailStockAsync([FromBody] PharmacyRetailStockModel model)
        {
            model = (PharmacyRetailStockModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.AddRetailStock(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the surgery kit stocks.
        /// </summary>
        /// <param name="productIds">The product ids.</param>
        /// <param name="retailPharmacyId">The retail pharmacy identifier.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-surgery-kit-stock")]
        public async Task<ActionResult> FetchSurgeryKitStocks(string productIds, int? retailPharmacyId)
        {
            if (string.IsNullOrEmpty(productIds))
            {
                return this.BadRequest("Product id is required");
            }

            var response = await this.pharmacyService.FetchSurgeryProductsStock(productIds, retailPharmacyId);
            return this.Success(response);
        }

        /// <summary>
        /// The add surgery kit sale bill.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("add-surgery-kit-sale-bill")]
        public async Task<ActionResult> AddSurgeryKitSaleBill([FromBody] SurgeryKitSaleModel model)
        {
            string logDescription = "";
            model = (SurgeryKitSaleModel)EmptyFilter.Handler(model);

            foreach (var product in model.Products)
            {
                var mainModel = new PharmacySaleBillModel
                {
                    BillType = model.BillType,
                    CreatedBy = model.CreatedBy,
                    Mobile = model.Mobile,
                    AdmissionId = null,
                    BillNumber = model.BillNumber,
                    NetAmount = product.NetAmount,
                    PatientId = model.PatientId,
                    PatientName = model.PatientName,
                    PharmacySaleHeaderId = model.PharmacySaleHeaderId,
                    ProviderName = model.ProviderName,
                    SaleDate = model.SaleDate,
                    PharmacyProductId = product.PharmacyProductId,
                    PharmacyRetailStockId = product.PharmacyRetailStockId,
                    Quantity = product.Quantity,
                    TaxAmount = product.TaxAmount,
                    TaxId = product.TaxId,
                    Total = product.Total,
                    Discount = product.Discount,
                    DiscountPerItem = product.DiscountPerItem,
                    ProviderId = model.ProviderId
                };

                string kitName = await this.pharmacyService.FindKitNameBySurgeryKitHeaderId((int)model.SurgeryKitHeaderId);
                if (mainModel.PharmacySaleHeaderId == 0)
                {
                    var (pharmacySaleHeaderId, res) = await this.pharmacyService.AddSaleBill(mainModel);
                    model.PharmacySaleHeaderId = pharmacySaleHeaderId;
                    model.BillNumber = res;
                    logDescription = $@"New Sales Bill Added Successfully<br/>Bill Number:'{model.BillNumber}'<br/>Patient Name:'{model.PatientName}'<br/>Medicine Type:'Surgery kit'<br/>KitName:'{kitName}'";
                }
                else
                {
                    var (pharmacySaleHeaderId, res) = await this.pharmacyService.UpdateSaleBill(mainModel);
                    model.PharmacySaleHeaderId = pharmacySaleHeaderId;
                    logDescription = $@"Sales Bill Updated Successfully<br/>Bill Number:'{model.BillNumber}'<br/>Patient Name:'{model.PatientName}'<br/>Medicine Type:'Surgery kit'<br/>KitName:'{kitName}'";
                }
            }
            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.LoginAccountId,
                PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Sales,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = logDescription
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            return this.Success(model.PharmacySaleHeaderId);
        }

        /// <summary>
        /// The update retail stock async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Route("update-stock")]
        public async Task<ActionResult> UpdateRetailStockAsync([FromBody] PharmacyRetailStockModel model)
        {
            model = (PharmacyRetailStockModel)EmptyFilter.Handler(model);
            if (string.IsNullOrEmpty(model.UpdateType))
            {
                return this.BadRequest();
            }

            int response;
            string logDescription;
            int pharmacyLogTypeId;

            if (model.UpdateType == "main")
            {
                response = await this.pharmacyService.UpdateMainStock(model);
                logDescription = $@"<b>MainStock</b> Details Updated Successfully.";
                pharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_Stock;
            }
            else
            {
                var retailStoreName = await this.pharmacyService.FindPharmacyRetailName(model.PharmacyRetailStockId);
                response = await this.pharmacyService.UpdateRetailStock(model);
                logDescription = $@"Retail Store : <b>{retailStoreName}</b> Stock Details <b>Updated</b> Successfully.";
                pharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_RetailStock;
            }

            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.LoginAccountId,
                PharmacyLogTypeId = pharmacyLogTypeId,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = logDescription
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            return this.Success(response);
        }

        /// <summary>
        /// The update sale bill quantity async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="location"></param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("update-sale-quantity")]
        public async Task<ActionResult> UpdateSaleBillQuantityAsync([FromBody] PharmacySaleBill model, [FromHeader] LocationHeader location)
        {
            model = (PharmacySaleBill)EmptyFilter.Handler(model);
            var locationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.UpdateSaleBillQuantity(model);

            var productModel = new ProductModel
            {
                PharmacyProductId = model.PharmacyProductId
            };
            var pharmacyProduct = (await this.pharmacyService.FetchPharmacyProduct(productModel)).ToList();
            var pharmacySaleHeader = (await this.pharmacyService.FetchSaleAddedBill(model.PharmacySaleHeaderId, null, locationId)).ToList();

            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.LoginAccountId,
                PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Sales,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = $@"Sales Quantity Updated Successfully<br/>Bill Number:'{pharmacySaleHeader[0].BillNumber}'<br/>Patient Name:'{pharmacySaleHeader[0].PatientName}'<br/>Product Name:'{pharmacyProduct[0].ProductName}'<br/>Quantity Updated:'{model.Quantity}'"
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            return this.Success(response);
        }

        /// <summary>
        /// The delete sale bill product async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="location"></param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("delete-sale-bill-product")]
        public async Task<ActionResult> DeleteSaleBillProductAsync([FromBody] PharmacySaleBill model, [FromHeader] LocationHeader location)
        {
            model = (PharmacySaleBill)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.DeleteSaleBillItem(model);

            var locationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;

            var productModel = new ProductModel
            {
                PharmacyProductId = model.PharmacyProductId
            };
            var pharmacyProduct = (await this.pharmacyService.FetchPharmacyProduct(productModel)).ToList();
            var pharmacySaleHeader = (await this.pharmacyService.FetchSaleAddedBill(model.PharmacySaleHeaderId, null, locationId)).ToList();

            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.LoginAccountId,
                PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Sales,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = $@"Sales Bill Product Deleted Successfully<br/>Bill Number:'{pharmacySaleHeader[0].BillNumber}'<br/>Patient Name:'{pharmacySaleHeader[0].PatientName}'<br/>Product Name:'{pharmacyProduct[0].ProductName}'"
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            return this.Success(response);
        }

        /// <summary>
        /// The delete sale bill product async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Route("delete-purchase-bill-product")]
        public async Task<ActionResult> DeletePurchaseBillProductAsync([FromBody] PharmacyPurchaseBill model)
        {
            model = (PharmacyPurchaseBill)EmptyFilter.Handler(model);
            var (response, header) = await this.pharmacyService.DeletePurchaseBillItems(model);
            if (response > 0)
            {
                var pharmacyPurchaseHeader = (await this.pharmacyService.FetchAddedPurchaseBillAsync(model.PharmacyPurchaseHeaderId, null)).ToList();
                if (pharmacyPurchaseHeader.Count > 0)
                {
                    var productModel = new ProductModel
                    {
                        PharmacyProductId = model.PharmacyProductId
                    };
                    var pharmacyProduct = (await this.pharmacyService.FetchPharmacyProduct(productModel)).ToList();

                    var pharmacyLogModel = new PharmacyLogModel
                    {
                        AccountId = model.LoginAccountId,
                        PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Purchase,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.Now,
                        LogDescription = $@"Purchase Bill Deleted Successfully<br/>Bill Number: <h6>{pharmacyPurchaseHeader[0].BillNumber}</h6><br/>Product Name:'{pharmacyProduct[0].ProductName}'"
                    };
                    await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                }
                else
                {
                    var pharmacyLogModel = new PharmacyLogModel
                    {
                        AccountId = model.LoginAccountId,
                        PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Purchase,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.Now,
                        LogDescription = $@"Purchase Bill with <br/>Bill Number:'{header.BillNumber}'<br/>deleted successfully."
                    };
                    await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                }
            }
            return this.Success(response);
        }

        /// <summary>
        /// The cancel sale bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Route("cancel-sale-bill")]
        public async Task<ActionResult> CancelSaleBillAsync([FromBody] PharmacySaleBill model)
        {
            model = (PharmacySaleBill)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.CancelSaleBill((int)model.PharmacySaleHeaderId);

            if (response > 0)
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.LoginAccountId,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Sales,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $@"Sales Bill Cancelled Successfully<br/>Bill Number:'{model.BillNumber}'<br/>Patient Name:'{model.PatientName}'",
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            }
            return this.Success(response);
        }

        /// <summary>
        /// The fetch pharmacy product with retail stock async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-product-with-stock")]
        public async Task<ActionResult> FetchPharmacyProductWithRetailStocksAsync([FromBody] ProductModel model)
        {
            var models = model ?? new ProductModel();
            var response = await this.pharmacyService.FetchPharmacyProductWithRetailStockAsync(models);
            return this.Success(response);
        }

        /// <summary>
        /// The move retail to main stock async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Route("move-retail-to-main-stock")]
        public async Task<ActionResult> MoveRetailToMainStockAsync([FromBody] PharmacyMoveQuantity model)
        {
            var models = (PharmacyMoveQuantity)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.MoveRetailStockToMainAsync(models);
            var retailStoreName = await this.pharmacyService.FindPharmacyRetailName(model.PharmacyRetailStockId);

            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.LoginAccountId,
                PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_RetailStock,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = $@"Retail Stock from <b>{retailStoreName}</b> Moved to Main Stock Successfully<br/>Quantity moved:'{model.Quantity}'<br/>Reason:'{model.Reason}'"
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            return this.Success(response);
        }

        /// <summary>
        /// The fetch product with main stock detail.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Route("get-main-stock-and-product")]
        public async Task<ActionResult> FetchProductWithMainStockDetail([FromBody] PharmacyStockModel model)
        {
            model = (PharmacyStockModel)EmptyFilter.Handler(model);
            var pharmacyStockId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedPharmacyStockId));
            var stocks = (await this.pharmacyService.FetchPharmacyStocks(new PharmacyStockModel { PharmacyStockId = pharmacyStockId, UnavailableStock = "yes" })).ToList();
            if (stocks.Count == 0)
            {
                return this.BadRequest("No Stock Found.");
            }

            var productDetail = (await this.pharmacyService.FetchPharmacyProduct(new ProductModel { PharmacyProductId = (int)stocks[0].PharmacyProductId })).ToList();

            if (productDetail.Count == 0)
            {
                return this.BadRequest("No Product Found.");
            }

            var output = new Models.Pharmacy.PharmacyCombinedModel
            {
                Products = productDetail[0],
                Stock = stocks[0]
            };

            return this.Success(output);
        }

        /// <summary>
        /// The fetch purchase bill item async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Route("get-purchase-bill-item")]
        public async Task<ActionResult> FetchPurchaseBillItemAsync([FromBody] PharmacyStockModel model)
        {
            model = (PharmacyStockModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchPurchaseBillItem(model.PharmacyStockId);
            return this.Success(response);
        }

        /// <summary>
        /// The return purchase bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Route("return-purchase-bill-item")]
        public async Task<ActionResult> ReturnPurchaseBillAsync([FromBody] PharmacyPurchaseReturnBillModel model)
        {
            model = (PharmacyPurchaseReturnBillModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.ReturnPurchaseBill(model);
            try
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.LoginAccountId,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Masters_Stock,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $@"Purchase Returned Successfully<br/>Bill No.:'{model.BillNumber}'<br/>Return Quantity:'{model.ReturnQuantity}'"
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            }
            catch (Exception)
            {
                // ignore
            }

            return this.Success(response);
        }

        /// <summary>
        /// Fetches the category revenue report.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-category-revenue")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyExplorerModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchCategoryRevenueReport([FromBody] PharmacyExplorerFilterModel model)
        {
            model = (PharmacyExplorerFilterModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchCategoryRevenue(model);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch pharmacy product wise revenue report async.
        /// </summary>
        /// <param name="model"></param>
        /// The id.       
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-product-revenue")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyExplorerModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchProductRevenueReport([FromBody] PharmacyExplorerFilterModel model)
        {
            model = (PharmacyExplorerFilterModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchProductRevenue(model);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch pharmacy product wise revenue report async.
        /// </summary>
        /// <param name="model"></param>
        /// The id.        
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-top-products-revenue")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyExplorerModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchTopProductsRevenueReport([FromBody] PharmacyExplorerFilterModel model)
        {
            model = (PharmacyExplorerFilterModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchTopProductsRevenue(model);
            return this.Success(response);
        }


        /// <summary>
        /// The add pharmacy sale bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("add-pay-type")]
        public async Task<ActionResult> AddPayTypeToSaleBillAsync([FromBody] PharmacySaleBillModel model)
        {
            var response = await this.pharmacyService.AddPayType(model);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch doctor collection in pharmacy revenue
        /// </summary>
        /// <param name="model"></param>
        /// The id.        
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-doctor-collection")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyDoctorCollection>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchDoctorCollectionAsync([FromBody] PharmacyExplorerFilterModel model)
        {
            model = (PharmacyExplorerFilterModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchDoctorCollection(model);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch employee collection in pharmacy revenue
        /// </summary>
        /// <param name="model"></param>
        /// The id.
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-employee-collection")]
        [ProducesResponseType(200, Type = typeof(List<PharmacyEmployeeCollection>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchEmployeeCollectionAsync([FromBody] PharmacyExplorerFilterModel model)
        {
            model = (PharmacyExplorerFilterModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchEmployeeCollection(model);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch all retail stores async.
        /// </summary>
        /// <param name="model">
        /// The id.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-all-retail-stores")]
        public async Task<ActionResult> FetchAllRetailStoresAsync([FromBody] RetailPharmacyModel model, [FromHeader] LocationHeader header)
        {
            model ??= new RetailPharmacyModel();
            model.LocationId = int.Parse(header.LocationId);
            var response = await this.pharmacyService.FetchAllRetailStores(model);
            return this.Success(response);
        }

        /// <summary>
        /// The delete retail store async.
        /// </summary>
        /// <param name="model">
        /// The id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("delete-retail-store")]
        public async Task<ActionResult> DeleteRetailStoreAsync([FromBody] RetailPharmacyModel model)
        {
            model = (RetailPharmacyModel)EmptyFilter.Handler(model);
            try
            {
                var response = await this.pharmacyService.DeleteRetailStoreAsync((int)model.RetailPharmacyId);
                return this.Success(response);
            }
            catch (Exception e)
            {
                return this.BadRequest(e.Message);
            }
        }

        /// <summary>
        /// The give discount async.
        /// </summary>
        /// <param name="model">
        /// The model
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("give-discount")]
        public async Task<ActionResult> GiveDiscountAsync([FromBody] DiscountBills model)
        {
            model = (DiscountBills)EmptyFilter.Handler(model);
            try
            {
                var response = await this.pharmacyService.DiscountOnBill(model);
                return this.Success(response);
            }
            catch (Exception e)
            {
                return this.BadRequest(e.Message);
            }
        }

        /// <summary>
        /// The revoke given discount async.
        /// </summary>
        /// <param name="model">
        /// The model
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("revoke-discount")]
        public async Task<ActionResult> RevokeGivenDiscountAsync([FromBody] DiscountBills model)
        {
            model = (DiscountBills)EmptyFilter.Handler(model);
            try
            {
                var response = await this.pharmacyService.RevokeDiscountedBill(model);
                return this.Success(response);
            }
            catch (Exception e)
            {
                return this.BadRequest(e.Message);
            }
        }

        /// <summary>
        /// The add new sales bill async.
        /// </summary>
        /// <param name="model">
        /// The model
        /// </param>
        /// <param name="location"></param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("add-new-sales-bill")]
        [Consumes("multipart/form-data")]
        [ProducesResponseType(typeof(int), 200)]
        public async Task<ActionResult> AddNewSalesBillAsync([FromForm] NewSalesBill model, [FromHeader] LocationHeader location)
        {
            var locationId = int.Parse(location.LocationId);
            model.Products = model.Products.Count > 0 ? model.Products : JsonConvert.DeserializeObject<List<NewSaleBillProductModel>>(model.ProductList);
            var id = await this.AddAsyncHelper(model, locationId);

            // commented because of performance issue.

            if (id > 0)
            {
                var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                if ((bool)WhatsAppMessage[0].Active)
                {
                    _ = this.whatsAppSMSSender.SendPharmacyWhatsAppMessage(model.Mobile, model.PatientName, "PharmacySale");
                }

            }
            else
            {
                return this.Success(new GenericResponse
                {
                    Status = GenericStatus.Error,
                    Data = id
                });
            }

            return this.Success(new GenericResponse
            {
                Status = GenericStatus.Success,
                Data = id
            });
        }

        /// <summary>
        /// Adds the asynchronous helper.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="locationId"></param>
        /// <returns></returns>
        [NonAction]
        public async Task<int> AddAsyncHelper(NewSalesBill model, int locationId)
        {
            model = (NewSalesBill)EmptyFilter.Handler(model);
            if (model.PatientId == null || model.PatientId == 0)
            {
                var patientId = await this.AddPatientsAsync(model);
                if (patientId == -1)
                {
                    return -409;
                }
                model.PatientId = patientId;
            }

            var (id, billNumber) = await this.pharmacyService.AddNewSalesBillAsync(model, locationId);

            try
            {
                if (id > 0)
                {
                    var pharmacyLogModel = new PharmacyLogModel
                    {
                        AccountId = model.LoginAccountId,
                        PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Sales,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.Now,
                        LogDescription = $@"New Sales Bill Added Successfully<br/>Bill Number:'{billNumber}'<br/>Patient Name:'{model.PatientName}'<br/>Type:'Medicine'"
                    };
                    await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                    if (model.AppointmentId != null && model.AppointmentId > 0)
                    {
                        await this.notificationService.UpdateReadStatus((int)model.AppointmentId, (int)ModulesMasterType.Pharmacy);
                    }
                }
            }
            catch (Exception)
            {
                // ignore
            }
            return id;
        }

        /// <summary>
        /// The fetch added purchase bill async.
        /// </summary>
        /// <param name="pharmacyHeaderId">
        /// The pharmacy header id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("purchase-bill-email")]
        public async Task<ActionResult> SendAddedPurchaseBillAsync(string pharmacyHeaderId)
        {
            if (string.IsNullOrEmpty(pharmacyHeaderId))
            {
                return this.BadRequest();
            }
            var response = await this.pharmacyService.FetchAddedBill(int.Parse(pharmacyHeaderId));

            if (this.runningEnvironment.CurrentEnvironment != "Local")
            {
                var userList = new List<AccountModel> { };

                if (this.runningEnvironment.CurrentEnvironment == "Production")
                {
                    userList.Add(new AccountModel { Email = "director@maasharada.com", FullName = "Director" });
                    userList.Add(new AccountModel { Email = "purchase@maasharada.com", FullName = "Purchase" });
                    userList.Add(new AccountModel { Email = "pharmacy@maasharada.com", FullName = "Pharmacy" });
                }
                else
                {
                    userList.Add(new AccountModel { Email = "psivakumar@docassistant.net", FullName = "Siva Kumar" });
                    userList.Add(new AccountModel { Email = "puday@sujainfo.net", FullName = "Uday" });
                }

                ProductEmailModel productEmail = new ProductEmailModel();
                productEmail.EmailProducts = new List<SendEmailModel>();

                foreach (var item in response)
                {
                    productEmail.CreatedByName = item.CreatedByName;
                    productEmail.BillDate = item.BillDate;
                    productEmail.BillType = item.BillType;
                    productEmail.BillNumber = item.BillNumber;

                    SendEmailModel sendEmail = new SendEmailModel();

                    sendEmail.CategoryName = item.CategoryName;
                    sendEmail.SupplierName = item.SupplierName;
                    sendEmail.ProductName = item.ProductName;
                    sendEmail.PurchaseRate = item.PurchaseRate;
                    sendEmail.GenericName = item.GenericName;
                    sendEmail.Quantity = item.Quantity;
                    sendEmail.Total = item.Total;
                    sendEmail.DiscountPerItem = item.DiscountPerItem;
                    sendEmail.Free = item.Free;
                    sendEmail.TaxAmount = item.TaxAmount;
                    sendEmail.NetAmount = item.NetAmount;
                    productEmail.EmailProducts.Add(sendEmail);

                }
                await this.emailSender.SendPharmacyMailAsync(userList, productEmail);
            }

            return this.Success(response);
        }

        /// <summary>
        /// Fetches the pharmacy products with stocks in bulk asynchronous.
        /// </summary>
        /// <param name="productIds">The product ids.</param>
        /// <param name="wareHouseId">The ware house id.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("pharmacy-stock-bulk")]
        public async Task<ActionResult> FetchPharmacyProductsWithStocksInBulkAsync(string productIds, int? wareHouseId)
        {
            if (string.IsNullOrEmpty(productIds))
            {
                return this.BadRequest("Invalid parameter");
            }
            var response = await this.pharmacyService.FetchMainStockForProductsInBulk(productIds, wareHouseId);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch Credit Purchased bills.
        /// </summary>
        /// /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="location"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("purchase-credit-bill")]
        public async Task<ActionResult> FetchCreditPurchaseBill([FromBody] PharmacyPurchaseReportBill model, [FromHeader] LocationHeader location)
        {
           //model.LocationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;          
            model.LocationId = model.LocationId > 0 ? model.LocationId :null;
            var response = await this.pharmacyService.FetchCreditPurchaseBillAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// The updating the Purchase Payment(credit Amount Due Paying ).
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("update-purchase-pay")]
        public async Task<ActionResult> UpdatePurchasePay([FromBody] PharmacyPurchaseReportBill model)
        {

            var response = await this.pharmacyService.UpdatePurchasePayAsync(model);

            var pharmacyLogModel = new PharmacyLogModel
            {
                AccountId = model.ModifiedBy,
                PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Purchase,
                LogFrom = (short)model.LoginRoleId,
                LogDate = DateTime.Now,
                LogDescription = $@" Credit Payment Cleared with Bill Number : <b>'{model.BillNumber}'</b>."
            };
            await this.pharmacyLogService.LogAsync(pharmacyLogModel);

            return this.Success(response);
        }

        /// <summary>
        /// Gets the pharmacy bill count.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("get-bill-count")]
        public async Task<ActionResult> GetPharmacyBillCount()
        {
            return this.Success(await this.pharmacyService.GetPharmacySaleBillHeaderCounts());
        }

        /// <summary>
        /// Corrects the GST calculation in pharmacy sale bill.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("correct-sale-bills")]
        public async Task<ActionResult> CorrectGSTCalculationINPharmacySaleBill([FromBody] PharmacyPurchaseReportBill model)
        {
            model = (PharmacyPurchaseReportBill)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.CorrectGSTCalculationInPharmacySale(model.PageSize, model.PageIndex);
            if (response == 0)
            {
                return this.BadRequest("All bills corrected successfully.");
            }
            return response > 0 ? this.Success("Updated") : this.BadRequest("Error occured while updating.");
        }

        /// <summary>
        /// Fetches the existing batch numbers.
        /// </summary>
        /// <param name="pharmacyProductId">The pharmacy product identifier.</param>
        /// <param name="location"></param>
        /// <returns></returns>
        [HttpGet]
        [Authorize]
        [Route("get-batch-numbers")]
        public async Task<ActionResult> FetchExistingBatchNumbers(int pharmacyProductId, [FromHeader] LocationHeader location)
        {
            var locationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchExistingBatchNumbers(pharmacyProductId, locationId);
            return this.Success(response ?? new List<string>());
        }

        /// <summary>
        /// Creates new purchase bill async.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns>
        /// <see cref="Task"/>
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("modify-new-purchase-bill")]
        public async Task<ActionResult> NewPurchaseBillAsync([FromBody] PurchaseBillHeaderModel model)
        {
            model = (PurchaseBillHeaderModel)EmptyFilter.Handler(model);
            if (model.Products.Count == 0)
            {
                return this.BadRequest("Please add some products to add purchase bill.");
            }

            var response = await this.pharmacyService.AddNewPurchaseBill(model);
            var pharmacyHeaderId = response;
            if (response > 0)
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.CreatedBy,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Purchase,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $@"Purchase Bill {(model.PharmacyPurchaseHeaderId > 0 ? "updated" : "added")} successfully with<br/>Bill Number:'{model.BillNumber} {model.WareHouseName}"
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                var responses = await this.pharmacyService.FetchAddedBill(pharmacyHeaderId);

                try
                {
                    if (this.runningEnvironment.CurrentEnvironment != "Local")
                    {
                        var userList = new List<AccountModel> { };

                        if (this.runningEnvironment.CurrentEnvironment == "Production")
                        {
                            userList.Add(new AccountModel { Email = "director@maasharada.com", FullName = "Director" });
                            userList.Add(new AccountModel { Email = "purchase@maasharada.com", FullName = "Purchase" });
                            userList.Add(new AccountModel { Email = "pharmacy@maasharada.com", FullName = "Pharmacy" });
                        }
                        else
                        {
                            userList.Add(new AccountModel { Email = "spchandana@sujainfo.net", FullName = "Priya Chandana" });
                            userList.Add(new AccountModel { Email = "ksatyavani@sujainfo.net", FullName = "Satyavani" });
                            userList.Add(new AccountModel { Email = "puday@sujainfo.net", FullName = "Uday" });
                        }

                        ProductEmailModel productEmail = new ProductEmailModel();
                        productEmail.EmailProducts = new List<SendEmailModel>();

                        foreach (var item in responses)
                        {
                            productEmail.CreatedByName = item.CreatedByName;
                            productEmail.BillDate = item.BillDate;
                            productEmail.BillType = item.BillType;
                            productEmail.BillNumber = item.BillNumber;

                            SendEmailModel sendEmail = new SendEmailModel();

                            sendEmail.CategoryName = item.CategoryName;
                            sendEmail.SupplierName = item.SupplierName;
                            sendEmail.ProductName = item.ProductName;
                            sendEmail.PurchaseRate = item.PurchaseRate;
                            sendEmail.GenericName = item.GenericName;
                            sendEmail.Quantity = item.Quantity;
                            sendEmail.Total = item.Total;
                            sendEmail.DiscountPerItem = item.DiscountPerItem;
                            sendEmail.Free = item.Free;
                            sendEmail.TaxAmount = item.TaxAmount;
                            sendEmail.NetAmount = item.NetAmount;
                            productEmail.EmailProducts.Add(sendEmail);

                        }
                        await this.emailSender.SendPharmacyMailAsync(userList, productEmail);
                    }
                }
                catch (Exception)
                {
                    return null;
                }
            }

            return response > 0 ? this.Success(response) : this.BadRequest("Some error occured in adding stocks for product.Please check the products.");
        }

        /// <summary>
        /// Adds the retail store indent asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("add-retail-store-indent")]
        public async Task<ActionResult> AddRetailStoreIndentAsync([FromBody] OTRaiseIndentModel model, [FromHeader] LocationHeader location)
        {
            model = (OTRaiseIndentModel)EmptyFilter.Handler(model);

            if (model.Products.Count == 0)
            {
                return this.BadRequest("The product can not be null.Please add some products to raise indent.");
            }
            model.LocationId = int.Parse(location.LocationId);
            var response = await this.pharmacyService.AddRetailStoreIndentAsync(model);
            if (response > 0)
            {
                var pharmacyLogModel = new PharmacyLogModel
                {
                    AccountId = model.CreatedBy,
                    PharmacyLogTypeId = (int)PharmacyLogTypes.RetailIndent,
                    LogFrom = model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $@"New Indent Request for {model.WareHouseName}"
                };
                await this.pharmacyLogService.LogAsync(pharmacyLogModel);
            }

            return response > 0 ? this.Success(response) : this.BadRequest("Sorry not able to raise indent now.Please try again..!");
        }


        /// <summary>
        /// Fetches the retail indents asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-retail-store-indent")]
        public async Task<ActionResult> FetchRetailIndentsAsync([FromBody] OTIndentModel model, [FromHeader] LocationHeader location)
        {
            model ??= new OTIndentModel();
            model.LocationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.FetchRetailIndentAsync(model);
            return this.Success(response);
        }


        /// <summary>
        /// Fetches the retail indent detail asynchronous.
        /// </summary>
        /// <param name="model">The indent header identifier.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-retail-indent-detail")]
        public async Task<ActionResult> FetchRetailIndentDetailAsync(OTIndentModel model)
        {
            if (model.IndentHeaderId == 0)
            {
                return this.BadRequest("Something wrong with supplied parameter.Please check..!!");
            }
            var response = await this.pharmacyService.FetchRetailIndentDetailAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// The fetch all retail stores async.
        /// </summary>
        /// <param name="model">
        /// The id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-all-retail-stores-only")]
        public async Task<ActionResult> FetchAllRetailStoresOnlyAsync([FromBody] RetailPharmacyModel model)
        {
            model ??= new RetailPharmacyModel();
            var response = await this.pharmacyService.FetchAllRetailStoresOnly(model);
            return this.Success(response);
        }

        /// <summary>
        /// The add retail store async.
        /// </summary>
        /// <param name="model">
        /// The id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("add-retail-store-new")]
        public async Task<ActionResult> AddRetailStore([FromBody] RetailPharmacyModel model, [FromHeader] LocationHeader header)
        {
            try
            {
                model = (RetailPharmacyModel)EmptyFilter.Handler(model);
                var response = await this.pharmacyService.CreateRetailStoreAsync(model);
                if (response > 0)
                {
                    var pharmacyLogModel = new PharmacyLogModel
                    {
                        AccountId = model.CreatedBy,
                        PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Retail_Store,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.Now,
                        LogDescription = $@"<b>{model.CreatedByName}</b> has {(model.RetailPharmacyId > 0 ? "updated" : "created")} the <b>{model.RetailName}</b>  successfully",
                        LocationId = Convert.ToInt32(header.LocationId)
                    };
                    await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                }
                return this.Success(response);
            }
            catch (Exception e)
            {
                if (e.Message.Contains($@"duplicate key value violates unique constraint ""RetailPharmacy_RetailName_key"""))
                {
                    return this.BadRequest("This store name already exists.");
                }
                else
                {
                    return this.BadRequest(e.Message);
                }
            }
        }

        /// <summary>
        /// The delete retail store async.
        /// </summary>
        /// <param name="model">
        /// The id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("deactivate-retail-store")]
        public async Task<ActionResult> DeActiveRetailStoreAsync([FromBody] RetailPharmacyModel model, [FromHeader] LocationHeader header)
        {           
            model = (RetailPharmacyModel)EmptyFilter.Handler(model);
            try
            {
                var response = await this.pharmacyService.DeActiveRetailStoreAsync((int)model.RetailPharmacyId, (int)model.LoginAccountId);
               
                if (response > 0)
                {
                    var pharmacyLogModel = new PharmacyLogModel
                    {
                        AccountId = model.LoginAccountId,
                        PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Retail_Store,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LogDescription = $@"<b>{model.ModifiedByName}</b> has {((bool)model.Active ? "Activated" : "Deactivated")} the <b>{model.RetailName}  </b> on {DateTime.UtcNow.AddMinutes(330).ToString("MM/dd/yyyy, hh:mm tt")} successfully",
                        LocationId = Convert.ToInt32(header.LocationId)
                    };
                    await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                }
               
                return Ok(new GenericResponse
                {
                    Status = response switch
                    {
                        -1 => GenericStatus.Error,
                        -2 => GenericStatus.Info,
                        _ => GenericStatus.Success
                    },
                    Data = response
                });
            }
            catch (Exception ex)
            {
                return Ok(new GenericResponse
                {
                    Status = GenericStatus.Error,
                    Message = ex.Message
                });
            }
        }

        /// <summary>
        /// The delete retail store async.
        /// </summary>
        /// <param name="model">
        /// The id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("activate-retail-store")]
        public async Task<ActionResult> ActiveRetailStoreAsync([FromBody] RetailPharmacyModel model, [FromHeader] LocationHeader header)
        {
            model = (RetailPharmacyModel)EmptyFilter.Handler(model);

            try
            {
                var response = await this.pharmacyService.ToActiveRetailStoreAsync((int)model.RetailPharmacyId, (int)model.LoginAccountId);
                if (response == 0)
                {
                    return this.ServerError();
                }
                if (response > 0)
                {
                    var pharmacyLogModel = new PharmacyLogModel
                    {
                        AccountId = model.LoginAccountId,
                        PharmacyLogTypeId = (int)PharmacyLogTypes.Pharmacy_Retail_Store,
                        LogFrom = (short)model.LoginRoleId,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LogDescription = $@"<b>{model.ModifiedByName}</b> has {((bool)model.Active ? "Activated" : "Deactivated")} the <b>{model.RetailName}  </b> on {DateTime.UtcNow.AddMinutes(330).ToString("MM/dd/yyyy, hh:mm tt")} successfully",
                        LocationId = Convert.ToInt32(header.LocationId)
                    };
                    await this.pharmacyLogService.LogAsync(pharmacyLogModel);
                }

                return Ok(new GenericResponse
                {
                    Status = response switch
                    {
                        -1 => GenericStatus.Error,
                        -2 => GenericStatus.Info,
                        _ => GenericStatus.Success
                    },
                    Data = response
                });
            }
            catch (Exception ex)
            {
                return Ok(new GenericResponse
                {
                    Status = GenericStatus.Error,
                    Message = ex.Message
                });
            }
        }

        /// <summary>
        /// The fetch pharmacy purchase bill.
        /// </summary>
        /// <param name="pharmacyPurchaseHeaderId"></param>      
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("fetch-Pharmacy-Credit-Purchase-bill")]
        public async Task<ActionResult> FetchPharmacyCreditPurchaseBill(string pharmacyPurchaseHeaderId)
        {
            if (string.IsNullOrEmpty(pharmacyPurchaseHeaderId))
            {
                return this.BadRequest();
            }

            var response = await this.pharmacyService.FetchPharmacyCreditPurchaseBillAsync(int.Parse(pharmacyPurchaseHeaderId));

            return this.Success(response);
        }

        /// <summary>
        /// The fetch pharmacy purchase bill.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Route("fetch-pharmacy-retail-users")]
        public async Task<ActionResult> FetchPharmacyUsersRetail(int? accountId, int? pharmacyWareHouseId)
        {
            if (accountId == null && pharmacyWareHouseId == null)
            {
                return this.BadRequest();
            }
            var response = await this.pharmacyService.FetchPharmacyUsersRetailAsync(accountId, pharmacyWareHouseId);
            return this.Success(response);

        }

        /// <summary>
        /// The fetch added sales bill async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-added-sales-bill-for-patient")]
        public async Task<ActionResult> FetchAddedSalesBillForPatientAsync([FromBody] PharmacySaleBill model)
        {
            model = (PharmacySaleBill)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchSaleAddedBill(model.PharmacySaleHeaderId, string.Empty, (int?)null);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the product purchase history asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        [Route("fetch-product-purchase-history")]
        public async Task<ActionResult> FetchProductPurchaseHistoryAsync([FromBody] PurchaseBillHistoryModel model)
        {
            model = (PurchaseBillHistoryModel)EmptyFilter.Handler(model);
            var response = await this.pharmacyService.FetchProductPurchaseHistoryAsync(model);
            return this.Success(response);
        }

        [AllowAnonymous]
        [HttpGet]
        [Route("fetch-drugs")]
        public async Task<ActionResult> FetchDBDrugsAsync(string term)
        {
            return this.Success(await this.pharmacyService.FetchDrugAsync(term));
        }

        /// <summary>
        /// Modifies the med frequency asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-med-frequency")]
        public async Task<ActionResult> ModifyMedFrequencyAsync([FromBody] MedFrequencyMasterModel model)
        {
            model = (MedFrequencyMasterModel)EmptyFilter.Handler(model);
            var res = await this.pharmacyService.ModifyMedicationFreqAsync(model);
            return this.Success(res);
        }

        /// <summary>
        /// Modifies the med frequency asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-med-frequency")]
        public async Task<ActionResult> FetchMedFrequencyAsync([FromBody] MedFrequencyMasterModel model)
        {
            model ??= new MedFrequencyMasterModel();
            var res = await this.pharmacyService.FetchMedicationFreqAsync(model);
            return this.Success(res);
        }

        /// <summary>
        /// Changes the med frequency status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("change-med-frequency-status")]
        public async Task<ActionResult> ChangeMedFrequencyStatusAsync([FromBody] MedFrequencyMasterModel model)
        {
            model = (MedFrequencyMasterModel)EmptyFilter.Handler(model);
            var res = await this.pharmacyService.ChangeActiveStatusForMedFrequency(model);
            return this.Success(res);
        }


        /// <summary>
        /// Checks the products.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        private async Task<ProductModel> CheckProducts(ProductModel model)
        {
            if (model.CompanyId == 0)
            {
                var checkCompanyExits = await this.companyService.FetchAsync(new CompanyModel { TypeOf = "pharmacyCompany", Name = model.CompanyName });
                if (checkCompanyExits == null)
                {
                    var newCompany = new CompanyModel
                    {
                        Name = model.CompanyName,
                        TypeOf = "pharmacyCompany",
                        Location = "Hyderabad"
                    };

                    newCompany.CompanyId = await this.companyService.InsertCompanyAsync(newCompany);
                    model.CompanyId = newCompany.CompanyId;
                }
                else
                {
                    model.CompanyId = checkCompanyExits.CompanyId;
                }
            }
            LookupValueModel lookupModel = new LookupValueModel();

            if (model.CategoryId == 0)
            {
                lookupModel.Name = "PharmacyCategory";
                lookupModel.LookupValueName = model.CategoryName;
                var category = await this.CommonLookupValuesAsync(lookupModel);
                model.CategoryId = category.LookupValueId;
            }

            if (model.TaxId == 0)
            {
                lookupModel.Name = "PharmacyGst";
                lookupModel.LookupValueName = model.Tax;
                var gst = await this.CommonLookupValuesAsync(lookupModel);
                model.TaxId = gst.LookupValueId;
            }

            //if (model.RackId == 0)
            //{
            //    lookupModel.Name = "PharmacyRack";
            //    lookupModel.LookupValueName = model.RackName;
            //    var rack = await this.CommonLookupValuesAsync(lookupModel);
            //    model.RackId = rack.LookupValueId;
            //}

            if (model.PurchaseUnit == 0)
            {
                lookupModel.Name = "PharmacyUnit";
                lookupModel.LookupValueName = model.PurchaseUnitName;
                var purchaseUnit = await this.CommonLookupValuesAsync(lookupModel);
                model.PurchaseUnit = purchaseUnit.LookupValueId;
            }

            if (model.SaleUnit == 0)
            {
                lookupModel.Name = "PharmacyUnit";
                lookupModel.LookupValueName = model.SaleUnitName;
                var purchaseUnit = await this.CommonLookupValuesAsync(lookupModel);
                model.SaleUnit = purchaseUnit.LookupValueId;
            }

            return model;
        }

        /// <summary>
        /// Commons the lookup values asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        private async Task<LookupValueModel> CommonLookupValuesAsync(LookupValueModel model)
        {
            var allCategory = await this.pharmacyService.FetchLookupValues(model);
            var checkCategoryExists = allCategory?.ToList().Find(
            m => string.Equals(m.Name, model.LookupValueName, StringComparison.CurrentCultureIgnoreCase));
            if (checkCategoryExists == null)
            {
                var newCategory = new LookupValueModel
                {
                    LookupId = 0,
                    Name = model.LookupValueName
                };

                switch (model.Name)
                {
                    case "PharmacyCategory":
                        newCategory.LookupValueId = await this.pharmacyService.CreateCategoryAsync(newCategory);
                        break;
                    case "PharmacyUnit":
                        newCategory.LookupValueId = await this.pharmacyService.CreateUnitAsync(newCategory);
                        break;
                    case "PharmacyRack":
                        newCategory.LookupValueId = await this.pharmacyService.CreateRackAsync(newCategory);
                        break;
                    case "PharmacyGst":
                        newCategory.LookupValueId = await this.pharmacyService.CreateGstAsync(newCategory);
                        break;
                }

                return newCategory;
            }
            else
            {
                return checkCategoryExists;
            }
        }
       
        /// <summary>
        /// Adds the patients asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        private async Task<int> AddPatientsAsync(NewSalesBill model)
        {
            var singlePatient = new PatientModel();
            singlePatient.FirstName = model.PatientName;
            singlePatient.FullName = model.PatientName;
            singlePatient.Mobile = model.Mobile;
            singlePatient.CreatedBy = model.CreatedBy;
            singlePatient.LocationId = (int)model.LocationId;
            singlePatient.CountryId = 1;
            singlePatient.PaymentStatus = false;
            singlePatient.IsNewPatient = true;
            singlePatient.TempPatient = true;
            singlePatient.UMRNo = model.Mobile;

            List<PatientFamilyModel> singlePatientFamily = new List<PatientFamilyModel>();
            List<PatientEmergencyModel> singleEmergencyPatientInfo = new List<PatientEmergencyModel> { new PatientEmergencyModel { FullName = "", Relation = "", Mobile = "" } };
            try
            {
                var (accountId, patientId, guid) = await this.patientService.AddAsync(singlePatient, singleEmergencyPatientInfo, new List<PatientInsuranceModel>(), new PatientFamilyModel(), singlePatientFamily ?? new List<PatientFamilyModel>());
                return patientId;
            }
            catch (Exception ex)
            {
                return -1;
            }
        }
    }
}

