namespace Hims.Api.Controllers
{
    using System.Threading.Tasks;
    using Domain.Configurations;
    using Domain.Helpers;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Models;
    using Senders;
    using Shared.UserModels;
    using Utilities;

    using Hims.Infrastructure.Configurations;
    using Hims.Shared.Library.MailKit;
    using Hims.Shared.DataFilters;
    using Hims.Domain.Services;
    using System.Linq;
    using Hims.Shared.EntityModels;
    using Hims.Domain.Repositories.UnitOfWork;
    using Dapper;

    /// <inheritdoc />
    /// <summary>
    /// The application controller.
    /// </summary>
    [AllowAnonymous]
    [Route("api/application")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class ApplicationController : BaseController
    {
        /// <summary>
        /// The Application configuration.
        /// </summary>
        private readonly IApplicationConfiguration applicationConfiguration;

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

        /// <summary>
        /// The SMS helper.
        /// </summary>
        private readonly ISMSSender smsSender;

        /// <summary>
        /// The email sender.
        /// </summary>
        private readonly IEmailSender emailSender;

        /// <summary>
        /// The email helper.
        /// </summary>
        private readonly IEmailHelper emailHelper;

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

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

        /// <summary>
        /// The country services.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc />
        public ApplicationController(
            IApplicationConfiguration applicationConfiguration,
            IAESHelper aesHelper,
            ISMSSender smsSender,
            IEmailSender emailSender,
            IEmailHelper emailHelper,
            IWhatsAppSMSSender whatsAppSMSSender,
            ISettingService settingService,
            IUnitOfWork unitOfWork)
        {
            this.applicationConfiguration = applicationConfiguration;
            this.aesHelper = aesHelper;
            this.smsSender = smsSender;
            this.emailSender = emailSender;
            this.emailHelper = emailHelper;
            this.whatsAppSMSSender = whatsAppSMSSender;
            this.settingService = settingService;
            this.unitOfWork = unitOfWork;
        }

        /// <summary>
        /// To encode value.
        /// </summary>
        /// <param name="request">
        /// The request Model.
        /// </param>
        /// <returns>
        /// <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("encode")]
        public ActionResult Encode([FromBody] JsonRequest request) => this.Success(this.aesHelper.Encode(request.Json));

        /// <summary>
        /// To decode value.
        /// </summary>
        /// <param name="request">
        /// The request Model.
        /// </param>
        /// <returns>
        /// <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("decode")]
        public ActionResult Decode([FromBody] JsonRequest request) => this.Success(this.aesHelper.Decode(request.Json));

        /// <summary>
        /// To get Application Configuration.
        /// </summary>
        /// <returns>
        /// The Application Configuration model <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns Application Configuration.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpGet]
        [Route("get-app-configuration")]
        [ProducesResponseType(200, Type = typeof(IApplicationConfiguration))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> GetApplicationConfigurationAsync()
        {
            var config = await Task.Run(
                             () => new
                                       {
                                           this.applicationConfiguration.IOSAppLink,
                                           this.applicationConfiguration.AndroidAppLink
                                       });
            return config == null ? this.ServerError() : this.Success(config);
        }

        /// <summary>
        /// To send OTP to mobile number.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The OTP <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - OTP send to mobile number successful.
        /// - 400 - Invalid mobile number.
        /// - 500 - Problem with server side code.
        /// </remarks>
        [HttpPost]
        [Route("send-otp")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> SendOTPAsync([FromBody] SendOTPModel model)
        {
            
            if (!model.Username.Contains("@"))
            {
                string where = "";
                if (model.Username.ToLower().Contains("umr"))
                {
                    where += $@"where UPPER(p.""UMRNo"") = '{model.Username.Trim().ToUpper()}'";
                    var query = $@"select p.""PatientId"",p.""Mobile"",p.""CountryId"" from ""Patient""p {where}";

                    var patientData = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<PatientModel>(query);
                    if (patientData == null)
                    {
                        return null;
                    }
                    model.Username = patientData.Mobile;
                }
                var otp = CoreFilter.RandomNumbers(4);
                var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                if ((bool)WhatsAppMessage[0].Active)
                {
                    bool Ret = await this.whatsAppSMSSender.SendOTPAsync(model.Username, otp);
                }
                return this.Success(await this.smsSender.SendOTPAsync(model.Username, model.CountryId,otp));
            }
            else
            {
                return this.Success(await this.emailSender.SendOTPAsync(model.Username, null));
            }
        }
           // => !model.Username.Contains("@") ? this.Success(await this.smsSender.SendOTPAsync(model.Username, model.CountryId)) : this.Success(await this.emailSender.SendOTPAsync(model.Username, null));

        /// <summary>
        /// The send email patient.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("send-email-patient")]
        [ProducesResponseType(typeof(EmailModel), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(500)]
        public async Task<bool> SendEmailPatient([FromBody] EmailModel model)
        {
            try
            {
                var emailMessage = new EmailMessage
                                       {
                                           Importance = true,
                                           Priority = true,
                                           Subject = "Register for demo",

                                           // Content = await this.templateHelper.RenderTemplateAsync("Welcome", welcomeModel)
                                           Content = "Dear" + model.Name
                                                            + ",<p>You have registered with Hims for the demo.</p> <p>Thank you</p><p>Hims</p><p>https://www.Hims.com/</p><br/><p>This is an auto generated email from Hims.</p><p>Please do not reply.</p>"
                                       };

                emailMessage.ToAddresses.Add(new EmailAddress { Name = model.Name, Address = model.Email });
                await this.emailHelper.SendEmailAsync(emailMessage);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// The send email admin.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("send-email-admin")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(400)]
        public async Task<bool> SendEmailAdmin([FromBody] EmailModel model)
        {
            try
            {
                var emailMessage = new EmailMessage
                                       {
                                           Importance = true,
                                           Priority = true,
                                           Subject = "Register for demo",
                                           Content = "Name: " + model.Name + ",<br> Email: " + model.Email
                                                     + "<br>Phone: " + model.PhoneNo + "<br>Message: <p>"
                                                     + model.Message
                                                     + "</p><br/><p>This is an auto generated email from Hims.</p><p>Please do not reply.</p>"
                                       };

                emailMessage.ToAddresses.Add(new EmailAddress { Name = model.Name, Address = "sales@sujainfo.com" });
                await this.emailHelper.SendEmailAsync(emailMessage);
                return true;
            }
            catch
            {
                 return false;
            }
        }

        /// <summary>
        /// To get Application Configuration.
        /// </summary>
        /// <returns>
        /// The Application Configuration model <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns Application Configuration.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpGet]
        [Route("version")]
        [ProducesResponseType(200, Type = typeof(IApplicationConfiguration))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> GetVersion()
        {
            var config = await Task.Run(
                             () => new
                             {
                                 this.applicationConfiguration.Version
                             });
            return config == null ? this.ServerError() : this.Success(config);
        }
    }
}