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


    /// <inheritdoc />
    /// <summary>
    /// The resources controller.
    /// </summary>
    [Route("api/setting")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class SettingController : BaseController
    {

        /// <summary>
        /// The pharmacy service.
        /// </summary>
        private readonly IPharmacyService pharmacyService;

        /// <summary>
        /// The setting service.
        /// </summary>
        private readonly ISettingService settingService;
        private readonly IAuditLogService auditLogServices;
        /// <summary>
        /// The ftp helper.
        /// </summary>
        private readonly IFtpHelper ftpHelper;
        private readonly IFtpUploadHelper ftpUploadHelper;
        /// <summary>
        /// The running environment.
        /// </summary>
        private readonly IRunningEnvironment runningEnvironment;


        /// <inheritdoc />
        public SettingController(
            IPharmacyService pharmacyService,
            ISettingService settingService,
            IAuditLogService auditLogServices,
             IFtpHelper ftpHelper,
              IFtpUploadHelper ftpUploadHelper,
              IRunningEnvironment runningEnvironment
            )
        {
            this.pharmacyService = pharmacyService;
            this.settingService = settingService;
            this.auditLogServices = auditLogServices;
            this.ftpHelper = ftpHelper;
            this.ftpUploadHelper = ftpUploadHelper;
            this.runningEnvironment = runningEnvironment;
        }

        /// <summary>
        /// Adds the pharmacy stores asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="location"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("add-store-detail")]
        public async Task<ActionResult> AddPharmacyStoresAsync([FromBody] PharmacyStoreModel model, [FromHeader] LocationHeader location)
        {
            model = (PharmacyStoreModel)EmptyFilter.Handler(model);
            model.LocationId = location != null && !string.IsNullOrEmpty(location.LocationId) ? Convert.ToInt32(location.LocationId) : (int?)null;
            var response = await this.pharmacyService.AddRetailStoreDetails(model);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches the pharmacy stores setting.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("fetch-store-settings")]//
        public async Task<ActionResult> FetchPharmacyStoresSetting([FromHeader] LocationHeader location)
        {
            var locationId = location != null && !string.IsNullOrEmpty(location.LocationId) ? Convert.ToInt32(location.LocationId) : (int?)null;
            return this.Success(await this.pharmacyService.FetchAllStoresSettings(locationId));
        }

        /// <summary>
        /// Applies the settings to pharmacy.
        /// </summary>
        /// <param name="id">The identifier.</param>
        /// <param name="location"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("apply-store-settings")]
        public async Task<ActionResult> ApplySettingsToPharmacy(int id, [FromHeader] LocationHeader location)
        {
            if (id == 0)
            {
                return this.BadRequest("The parameter is not correct.");
            }

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

            return this.Success(await this.pharmacyService.ApplyStoreSettingInPharmacy(id, locationId));
        }

        /// <summary>
        /// Gets the applied settings to pharmacy.
        /// </summary>
        /// <returns></returns>        
        [AllowAnonymous]
        [HttpGet]
        [Route("get-applied-store-settings")]
        public async Task<ActionResult> GetAppliedSettingsToPharmacy(int? id, int? requestId, [FromHeader] LocationHeader location)
        {
            var locationId = location != null && !string.IsNullOrEmpty(location.LocationId) ? Convert.ToInt32(location.LocationId) : (int?)null;
            if (locationId == null || locationId == 0)
            {
                locationId = requestId;
            }
            return this.Success(await this.pharmacyService.GetAppliedSetting(id, locationId));
        }

        /// <summary>
        ///  to save/insert the Record
        /// </summary>
        /// <param name="model">
        /// The model
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("appointment-setting")]
        public async Task<ActionResult> AppointmentSettingAsync([FromBody] PrintSettingModel model)
        {
            try
            {
                var response = await this.settingService.AppointmentSettingAsync(model);

                return Ok(new GenericResponse
                {
                    Status = GenericStatus.Success,
                });
            }
            catch (Exception ex)
            {
                return Ok(new GenericResponse
                {
                    Status = GenericStatus.Error,
                    Message = ex.Message
                });
            }
        }

        /// <summary>
        /// The create async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("insert")]
        public async Task<ActionResult> CreateAsync([FromBody] SettingModel model, [FromHeader] LocationHeader header)
        {
            model = (SettingModel)EmptyFilter.Handler(model);
            model.LocationId = (int)(!string.IsNullOrEmpty(header.LocationId) ? int.Parse(header.LocationId) : (int?)null);

            int response;
            if (!string.IsNullOrEmpty(model.Image))
            {
                var filePath = $@"{this.runningEnvironment.CurrentEnvironment}/HIMS_Settings/Images";
                try
                {
                    await this.ftpUploadHelper.CreateDirectory(filePath);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }

                var dbPath = $@"{model.Name}_{model.Value}.jpg";
                filePath += $@"/{dbPath}";

                var uploadResponse = await this.ftpUploadHelper.UploadProfileImageAsync(model.Image, filePath);

                model.ImageUrl = $@"HIMS_Settings/Images/{dbPath}";
                if (uploadResponse <= 0)
                {
                    return this.BadRequest();
                }
            }
            if (model.SettingsId == 0)
            {
                response = await this.settingService.InsertAsync(model);
                if (response > 0)
                {
                    var auditLogModel = new AuditLogModel
                    {
                        AccountId = model.AccountId,
                        LogTypeId = (int)LogTypes.Settings,
                        LogFrom = (short)model.RoleId,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LogDescription = $@"<b>New Setting</b> of <b>{model.Name}</b>, for <b>{model.Type} </b><br>
                                         Added Successfully",
                        LocationId = model.LocationId
                    };

                    await this.auditLogServices.LogAsync(auditLogModel);
                }

            }
            else
            {
                response = await this.settingService.UpdateAsync(model);
                if (response > 0)
                {
                    var auditLogModel = new AuditLogModel
                    {
                        AccountId = model.AccountId,
                        LogTypeId = (int)LogTypes.Settings,
                        LogFrom = (short)model.RoleId,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LogDescription = $@"<b>Setting</b> of <b>{model.Name}</b>, for <b>{model.Type} </b><br>
                                        Updated Successfully",
                        LocationId = model.LocationId
                    };

                    await this.auditLogServices.LogAsync(auditLogModel);
                }

            }
            switch (response)
            {
                case -1:
                    return this.Conflict("Given Name for Setting has already been exists with us.");
                case 0:
                    return this.ServerError();
            }

            return this.Success(response);
        }

        /// <summary>
        /// The fetch all settings.
        /// </summary>
        /// <returns>
        /// The list of all settings record.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of setting.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpGet]
        //[Authorize]
        [AllowAnonymous]
        [Route("fetch")]
        public async Task<ActionResult> FetchAsync(string name, string type, bool? active)
        {
            var response = await this.settingService.FetchAsync(name, type, active);
            return response == null ? this.ServerError() : this.Success(response);
        }

        /// <summary>
        /// The fetch all settings.
        /// </summary>
        /// <returns>
        /// The list of all settings record.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of setting.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("update")]
        public async Task<ActionResult> UpdateAsync([FromBody] SettingModel model, [FromHeader] LocationHeader header)
        {
            model.LocationId = (int)(!string.IsNullOrEmpty(header.LocationId) ? int.Parse(header.LocationId) : (int?)null);
            try
            {
                var response = await this.settingService.UpdateAsync(model);
                if (response > 0)
                {
                    var auditLogModel = new AuditLogModel
                    {
                        AccountId = model.AccountId,
                        LogTypeId = (int)LogTypes.Settings,
                        LogFrom = (short)model.RoleId,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LogDescription = $@"<b>Setting</b> of <b>{model.Name}</b>, for <b>{model.Type} </b><br>
                                        <b>{((bool)model.Active ? "Activated" : "DeActivated")}</b> Successfully",

                        LocationId = model.LocationId
                    };

                    await this.auditLogServices.LogAsync(auditLogModel);
                }

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

    }
}
