namespace Hims.Api.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Domain.Services;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Shared.DataFilters;
    using Shared.EntityModels;
    using Shared.Library.Enums;
    using Shared.UserModels;
    using Shared.UserModels.OperationTheater;
    using Utilities;
    using Hims.Api.Models;
    using Hims.Shared.UserModels.ChargeModule;

    /// <inheritdoc />
    [Authorize]
    [Route("api/ot")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class OperationTheaterController : BaseController
    {
        /// <summary>
        /// The operation service.
        /// </summary>
        private readonly IOperationService operationService;

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

        /// <summary>
        /// The audit log services.
        /// </summary>
        private readonly IAuditLogService auditLogServices;
        /// <inheritdoc />
        public OperationTheaterController(IOperationService operationService, IChargeModuleService chargeModuleService, IAuditLogService auditLogServices)
        {
            this.operationService = operationService;
            this.chargeModuleService = chargeModuleService;
            this.auditLogServices = auditLogServices;
        }

        /// <summary>
        /// Raises the ot indent.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("raise-indent")]
        public async Task<ActionResult> RaiseOTIndent([FromBody] OTRaiseIndentModel model)
        {
            model = (OTRaiseIndentModel)EmptyFilter.Handler(model);
            var response = await this.operationService.RaiseOTIndent(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the raise indents.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-indent-header")]
        public async Task<ActionResult> FetchRaiseIndents([FromBody] OTIndentModel model)
        {
            model ??= new OTIndentModel();
            var response = await this.operationService.FetchRaisedIndents(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the indent details asynchronous.
        /// </summary>
        /// <param name="otIndentHeaderId">The ot indent header identifier.</param>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-indent-detail")]
        public async Task<ActionResult> FetchIndentDetailsAsync(int otIndentHeaderId)
        {
            if (otIndentHeaderId == 0)
            {
                return this.BadRequest("Parameters not correct.");
            }
            var response = await this.operationService.FetchIndentDetails(otIndentHeaderId);
            return this.Success(response);
        }

        /// <summary>
        /// Gets the pending indent count.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("pending-indent-count")]
        public async Task<ActionResult> GetPendingIndentCount(string type)
        {
            if (string.IsNullOrEmpty(type)) { return this.BadRequest(); }
            return this.Success(await this.operationService.GetPendingIndentCount(type));
        }

        /// <summary>
        /// Fetches the operation stock asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-operation-stock")]
        public async Task<ActionResult> FetchOperationStockAsync([FromBody] PharmacyStockModel model)
        {
            model ??= new PharmacyStockModel();
            var response = await this.operationService.FetchOperationStocks(model);
            return this.Success(response);
        }

        /// <summary>
        /// Modifies the surgery asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("modify-surgery")]
        public async Task<ActionResult> ModifySurgeryAsync([FromBody] SurgeryModel model, [FromHeader] LocationHeader header)
        {
            model = (SurgeryModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);
            var response = model.SurgeryId == 0 ? await this.operationService.InsertSurgeryAsync(model) : await this.operationService.UpdateSurgeryAsync(model);
            if (response > 0)
            {
                var auditLogModel = new AuditLogModel
                {
                    AccountId = model.CreatedBy,
                    LogTypeId = (int)LogTypes.Surgery,
                    LogFrom = (int)AccountType.Administrator,
                    LogDate = DateTime.UtcNow.AddMinutes(330),
                    LogDescription = $@" { model.CreatedByName } has {(model.SurgeryId > 0 ? "Updated" : "Added")} Surgery <b>{model.Name}</b> on { DateTime.UtcNow.AddMinutes(330) }",
                    LocationId = Convert.ToInt32(header.LocationId)
                };
                await this.auditLogServices.LogAsync(auditLogModel);
            }
            return this.Success(response);
        }

        /// <summary>
        /// Fetches all surgery asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch-all-surgery")]
        public async Task<ActionResult> FetchAllSurgeryAsync([FromBody] SurgeryModel model, [FromHeader] LocationHeader header)
        {
            model ??= new SurgeryModel();          
                 model.LocationId = int.Parse(header.LocationId);
            var response = await this.operationService.FetchAllSurgeryAsync(model);
            return this.Success(response);
        }


        [HttpPost]
        [Route("modify-status")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> ModifyStatusAsync([FromBody] SurgeryModel model, [FromHeader] LocationHeader header)
        {
            model = (SurgeryModel)EmptyFilter.Handler(model);
            var response = await this.operationService.ActivateOrDeactivateTest(model);
            if (response == 0)
            {
                return this.ServerError();
            }
            if (response > 0)
            {
                var auditLogModel = new AuditLogModel
                {
                    AccountId = model.ModifiedBy,
                    LogTypeId = (int)LogTypes.Surgery,
                    LogFrom = (int)AccountType.Administrator,
                    LogDate = DateTime.UtcNow.AddMinutes(330),                    
                    LogDescription = $@"<b>{model.CreatedByName}</b> has {((bool)model.Active ? "Activated" : "Deactivated")} the <b>{model.Name}  </b> on { DateTime.UtcNow.AddMinutes(330) } successfully",
                    LocationId = Convert.ToInt32(header.LocationId)
                };
                await this.auditLogServices.LogAsync(auditLogModel);
            }
            return this.Success(response);

        }

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

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

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

            return this.Success(response);
        }
    }
}