namespace Hims.Api.Controllers
{
    using Domain.Services;
    using Hims.Api.Models;
    using Hims.Shared.Library.Enums;
    using Hims.Shared.UserModels.Inventory;
    using Hims.Shared.UserModels.Pharmacy;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Shared.DataFilters;
    using Shared.EntityModels;
    using System;
    using System.Threading.Tasks;
    using Utilities;

    /// <summary>
    /// The inventory store controller.
    /// </summary>
    [Authorize]
    [Route("api/inventory-store")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class InventoryStoreController : BaseController
    {
        /// <summary>
        /// The inventory store service.
        /// </summary>
        private readonly IInventoryStoreService inventoryStoreService;

        /// <summary>
        /// The inventory log service.
        /// </summary>
        private readonly IInventoryLogService inventoryLogService;

        /// <inheritdoc />
        public InventoryStoreController(IInventoryStoreService inventoryStoreService, IInventoryLogService inventoryLogService)
        {
            this.inventoryStoreService = inventoryStoreService;
            this.inventoryLogService = inventoryLogService;
        }

        /// <summary>
        /// Modifies the ware house asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-ware-house")]
        public async Task<ActionResult> ModifyWareHouseAsync([FromBody] InventoryWareHouseModel model)
        {
            model = (InventoryWareHouseModel)EmptyFilter.Handler(model);
            var response = model.InventoryWareHouseId == 0 ? await this.inventoryStoreService.InsertInventoryWareHouse(model) : await this.inventoryStoreService.UpdateInventoryWareHouse(model);

            if (response == -2) { return this.BadRequest("The warehouse name already exists."); }

            try
            {
                var logModel = new InventoryLogModel
                {
                    AccountId = model.CreatedBy,
                    InventoryLogTypeId = (int)InventoryLogTypes.WareHouse,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $@"<b>{model.CreatedByName}</b> has {(model.InventoryWareHouseId > 0 ? "updated" : "created")} the <b>{model.Name}</b>  successfully"
                };
                await this.inventoryLogService.LogAsync(logModel);
            }
            catch (Exception)
            {
                // ignore
            }


            return this.Success(response);
        }

        /// <summary>
        /// Fetches all inventory ware house asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-all-warehouse")]
        public async Task<ActionResult> FetchAllInventoryWareHouseAsync([FromBody] InventoryWareHouseModel model, [FromHeader] LocationHeader header)
        {
            model ??= new InventoryWareHouseModel();
            model.LocationId = int.Parse(header.LocationId);
            var response = await this.inventoryStoreService.FetchAllWarehousesAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the ware house status asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-warehouse-status")]
        public async Task<ActionResult> ModifyWareHouseStatusAsync([FromBody] InventoryWareHouseModel model)
        {
            model = (InventoryWareHouseModel)EmptyFilter.Handler(model);
            var response = await this.inventoryStoreService.ActivateOrDeactivateWareHouse(model);

            try
            {
                var logModel = new InventoryLogModel
                {
                    AccountId = model.CreatedBy,
                    InventoryLogTypeId = (int)InventoryLogTypes.WareHouse,
                    LogFrom = (short)model.LoginRoleId,
                    LogDate = DateTime.Now,
                    LogDescription = $@"<b>{model.CreatedByName}</b> has {((bool)model.Active ? "Activated" : "Deactivated")} the {model.Name}  successfully"
                };
                await this.inventoryLogService.LogAsync(logModel);
            }
            catch (Exception)
            {
                // ignore
            }

            return this.Success(response);
        }

        /// <summary>
        /// Modifies the inventory department asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-department")]
        public async Task<ActionResult> ModifyInventoryDepartmentAsync([FromBody] PharmacyDepartmentModel model, [FromHeader] LocationHeader header)
        {
            model = (PharmacyDepartmentModel)EmptyFilter.Handler(model);
            model.LocationId = !string.IsNullOrEmpty(header.LocationId) ? int.Parse(header.LocationId) : (int?)null;
            var response = await this.inventoryStoreService.ModifyInventoryDepartment(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the inventory department asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-inventory-department")]
        public async Task<ActionResult> FetchInventoryDepartmentAsync([FromBody] PharmacyDepartmentModel model, [FromHeader] LocationHeader header)
        {
            model ??= new PharmacyDepartmentModel();
            model.LocationId = !string.IsNullOrEmpty(header.LocationId) ? int.Parse(header.LocationId) : (int?)null;
            var response = await this.inventoryStoreService.FetchInventoryDepartmentAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches all inventory ware house based on user asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-warehouses-based-on-user")]
        public async Task<ActionResult> FetchAllInventoryWareHouseBasedOnUserAsync([FromBody] InventoryWareHouseModel model, [FromHeader] LocationHeader header)
        {
            model ??= new InventoryWareHouseModel();
            model.LocationId = int.Parse(header.LocationId);
            var response = await this.inventoryStoreService.FetchAllWarehousesBasedOnUserAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches all department based on user asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-inventory-department-based-on-user")]
        public async Task<ActionResult> FetchAllDepartmentBasedOnUserAsync([FromBody] PharmacyDepartmentModel model, [FromHeader] LocationHeader header)
        {
            model ??= new PharmacyDepartmentModel();
            model.LocationId = !string.IsNullOrEmpty(header.LocationId) ? int.Parse(header.LocationId) : (int?)null;
            var response = await this.inventoryStoreService.FetchInventoryDepartmentBasedOnUserAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the department stocks.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-department-stock")]
        public async Task<ActionResult> FetchDepartmentStocks([FromBody] InventoryDepartmentalStockModel model, [FromHeader] LocationHeader header)
        {
            model ??= new InventoryDepartmentalStockModel();
            model.LocationId = !string.IsNullOrEmpty(header.LocationId) ? int.Parse(header.LocationId) : (int?)null;
            var response = await this.inventoryStoreService.FetchInventoryDepartmentalStockAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the inventory racks asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("get-inventory-rack")]
        public async Task<ActionResult> FetchInventoryRacksAsync([FromBody] InventoryProductRackModel model)
        {
            model = (InventoryProductRackModel)EmptyFilter.Handler(model);
            var response = await this.inventoryStoreService.FetchRackDepartmentWiseAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the product details asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-product-detail")]
        public async Task<ActionResult> ModifyProductDetailsAsync([FromBody] InventoryProductDetailModel model)
        {
            model = (InventoryProductDetailModel)EmptyFilter.Handler(model);
            var response = await this.inventoryStoreService.AddInventoryProductAdditionalDetailsAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Adds the departmental consumption asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("add-departmental-consumption")]
        public async Task<ActionResult> AddDepartmentalConsumptionAsync([FromBody] InventoryDepartmentConsumptionModel model)
        {
            model = (InventoryDepartmentConsumptionModel)EmptyFilter.Handler(model);
            var response = await this.inventoryStoreService.AddDepartmentStockConsumptionAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the departmental consumption history asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-departmental-consumption-history")]
        public async Task<ActionResult> FetchDepartmentalConsumptionHistoryAsync([FromBody] InventoryDepartmentConsumptionModel model)
        {
            model = (InventoryDepartmentConsumptionModel)EmptyFilter.Handler(model);
            var response = await this.inventoryStoreService.FetchDepartmentalConsumptionProductsAsync(model);
            return this.Success(response);
        }
    }
}

