#nullable enable
namespace Hims.Infrastructure.Helpers
{
    using System;
    using System.Threading.Tasks;
    using Hims.Domain.Configurations;
    using Hims.Domain.Helpers;
    using Hims.Shared.EntityModels;
    using RestSharp;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Serialization;

    /// <inheritdoc />
    public class KaleyraSMSHelper : IKaleyraSMSHelper
    {
        /// <summary>
        /// The application configuration.
        /// </summary>
        private readonly IApplicationConfiguration applicationConfiguration;

        /// <summary>
        /// Initializes a new instance of the <see cref="SMSHelper"/> class.
        /// </summary>
        /// <param name="applicationConfiguration">
        /// The application Configuration.
        /// </param>
        public KaleyraSMSHelper(IApplicationConfiguration applicationConfiguration)
        {
            this.applicationConfiguration = applicationConfiguration;
        }

        /// <inheritdoc />
        public async Task<IRestResponse?> SendSMSAsync(string mobile, string body, CountryModel countryModel, string templateId)
        {
            if (!this.applicationConfiguration.AllowSMSSending)
            {
                return new RestResponse();
            }

            if (countryModel == null || string.IsNullOrEmpty(countryModel.SMSUrl))
            {
                return null!;
            }

            mobile = string.IsNullOrEmpty(mobile) ? this.applicationConfiguration.DefaultMobile : mobile;
            countryModel.CountryCode = "+" + countryModel.CountryCode;

            var isOTP = body.Contains("verification code");

            var client = new RestClient(countryModel.SMSUrl);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddHeader("api-key", countryModel.SMSAuthorization);

            request.AddParameter("to", countryModel.CountryCode + mobile);
            request.AddParameter("sender", countryModel.SMSFrom);
            request.AddParameter("body", body);
            if (countryModel.CountryCode == "+91")
            {
                request.AddParameter("template_id", templateId);
            }
            request.AddParameter("type", isOTP ? "OTP" : "TXN");
            return await client.ExecuteAsync(request);
        }

        /// <inheritdoc />
        public async Task<Tuple<IRestResponse?, string>> SendReportSMSAsync(string mobile, string body, CountryModel countryModel, string templateId, string url)
        {
            if (!this.applicationConfiguration.AllowSMSSending)
            {
                return new Tuple<IRestResponse?, string>(new RestResponse(), null);
            }

            if (string.IsNullOrEmpty(countryModel.SMSUrl))
            {
                return new Tuple<IRestResponse?, string>(null, null);
            }

            if (string.IsNullOrEmpty(url))
            {
                return new Tuple<IRestResponse?, string>(null, null);
            }

            var tinyURLBody = new TinyUrlBody
            {
                URL = url,
                Domain = "tiny.one",
                Alias = string.Empty,
                Tags = string.Empty
            };

            var tinyUrl = new RestClient(this.applicationConfiguration.TinyUrlLink);
            var tinyUrlRequest = new RestRequest(Method.POST);
            tinyUrlRequest.AddQueryParameter("api_token", this.applicationConfiguration.TinyUrlAuthToken);
            tinyUrlRequest.AddHeader("Content-Type", "application/json");
            tinyUrlRequest.AddHeader("Accept", "application/json");
            var test = JsonConvert.SerializeObject(tinyURLBody, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            });
            tinyUrlRequest.AddJsonBody(test);

            var shortUrlRequest = await tinyUrl.ExecuteAsync<object>(tinyUrlRequest);
            var shortURl = string.Empty;
            if (shortUrlRequest.StatusCode == System.Net.HttpStatusCode.OK)
            {
                // shortURl += shortUrlRequest.Content;
                var testObj = JsonConvert.DeserializeObject<TinyURLResponseMainBody>(shortUrlRequest.Content);
                shortURl += (testObj != null && testObj.Data != null && !string.IsNullOrEmpty(testObj.Data.tiny_url)) ? testObj.Data.tiny_url : url;
            }

            body += shortURl;
            body += $@" to view. - CareAxes";

            mobile = string.IsNullOrEmpty(mobile) ? this.applicationConfiguration.DefaultMobile : mobile;
            countryModel.CountryCode = "+" + countryModel.CountryCode;

            var isOTP = body.Contains("verification code");

            var client = new RestClient(countryModel.SMSUrl);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddHeader("api-key", countryModel.SMSAuthorization);

            request.AddParameter("to", countryModel.CountryCode + mobile);
            request.AddParameter("sender", countryModel.SMSFrom);
            request.AddParameter("body", body);
            if (countryModel.CountryCode == "+91")
            {
                request.AddParameter("template_id", templateId);
            }
            request.AddParameter("type", isOTP ? "OTP" : "TXN");
            return new Tuple<IRestResponse?, string>(await client.ExecuteAsync(request), shortURl);
        }

        public async Task<Tuple<IRestResponse?, string>> SendPdfLinkSMSAsync(string mobile, string body, CountryModel countryModel, string templateId, string url)
        {
            if (!this.applicationConfiguration.AllowSMSSending)
            {
                return new Tuple<IRestResponse?, string>(new RestResponse(), null);
            }

            if (string.IsNullOrEmpty(countryModel.SMSUrl))
            {
                return new Tuple<IRestResponse?, string>(null, null);
            }

            if (string.IsNullOrEmpty(url))
            {
                return new Tuple<IRestResponse?, string>(null, null);
            }

            var tinyURLBody = new TinyUrlBody
            {
                URL = url,
                Domain = "tiny.one",
                Alias = string.Empty,
                Tags = string.Empty
            };

            var tinyUrl = new RestClient(this.applicationConfiguration.TinyUrlLink);
            var tinyUrlRequest = new RestRequest(Method.POST);
            tinyUrlRequest.AddQueryParameter("api_token", this.applicationConfiguration.TinyUrlAuthToken);
            tinyUrlRequest.AddHeader("Content-Type", "application/json");
            tinyUrlRequest.AddHeader("Accept", "application/json");
            var test = JsonConvert.SerializeObject(tinyURLBody, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            });
            tinyUrlRequest.AddJsonBody(test);

            var shortUrlRequest = await tinyUrl.ExecuteAsync<object>(tinyUrlRequest);
            var shortURl = string.Empty;
            if (shortUrlRequest.StatusCode == System.Net.HttpStatusCode.OK)
            {
                // shortURl += shortUrlRequest.Content;
                var testObj = JsonConvert.DeserializeObject<TinyURLResponseMainBody>(shortUrlRequest.Content);
                shortURl += (testObj != null && testObj.Data != null && !string.IsNullOrEmpty(testObj.Data.tiny_url)) ? testObj.Data.tiny_url : url;
            }

            body += url;
            body += $@" to view. - CareAxes";

            mobile = string.IsNullOrEmpty(mobile) ? this.applicationConfiguration.DefaultMobile : mobile;
            countryModel.CountryCode = "+" + countryModel.CountryCode;

            var isOTP = body.Contains("verification code");

            var client = new RestClient(countryModel.SMSUrl);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddHeader("api-key", countryModel.SMSAuthorization);

            request.AddParameter("to", countryModel.CountryCode + mobile);
            request.AddParameter("sender", countryModel.SMSFrom);
            request.AddParameter("body", body);
            if (countryModel.CountryCode == "+91")
            {
                request.AddParameter("template_id", templateId);
            }
            request.AddParameter("type", isOTP ? "OTP" : "TXN");
            return new Tuple<IRestResponse?, string>(await client.ExecuteAsync(request), url);
        }

    }
}

/// <summary>
/// The tiny url body.
/// </summary>
public class TinyUrlBody
{
    /// <summary>
    /// Gets or sets the URL.
    /// </summary>
    /// <value>
    /// The URL.
    /// </value>
    public string? URL { get; set; }

    /// <summary>
    /// Gets or sets the domain.
    /// </summary>
    /// <value>
    /// The domain.
    /// </value>
    public string? Domain { get; set; }

    /// <summary>
    /// Gets or sets the alias.
    /// </summary>
    /// <value>
    /// The alias.
    /// </value>
    public string? Alias { get; set; }

    /// <summary>
    /// Gets or sets the tags.
    /// </summary>
    /// <value>
    /// The tags.
    /// </value>
    public string? Tags { get; set; }
}

public class TinyURLResponseMainBody
{
    /// <summary>
    /// Gets or sets the data.
    /// </summary>
    /// <value>
    /// The data.
    /// </value>
    public TinyUrlData? Data { get; set; }

    /// <summary>
    /// Gets or sets the code.
    /// </summary>
    /// <value>
    /// The code.
    /// </value>
    public int Code { get; set; }
}

public class TinyUrlData
{
    /// <summary>
    /// Gets or sets the URL.
    /// </summary>
    /// <value>
    /// The URL.
    /// </value>
    public string? url { get; set; }

    /// <summary>
    /// Gets or sets the domain.
    /// </summary>
    /// <value>
    /// The domain.
    /// </value>
    public string? domain { get; set; }

    /// <summary>
    /// Gets or sets the alias.
    /// </summary>
    /// <value>
    /// The alias.
    /// </value>
    public string? alias { get; set; }

    /// <summary>
    /// Gets or sets the tiny URL.
    /// </summary>
    /// <value>
    /// The tiny URL.
    /// </value>
    public string? tiny_url { get; set; }
}