using EVCB_OCPP.Domain;
using EVCB_OCPP.Packet.Messages.SubTypes;
using EVCB_OCPP.WSServer.Dto;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace EVCB_OCPP.WSServer.Service
{
    internal class CPOOuterResponse
    {
        public CPOOuterResponse()
        {
            StatusCode = 0;

        }

        public int StatusCode { set; get; }

        public string StatusMessage { set; get; }

        public string Data { set; get; }

        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string SerialNo { set; get; }


        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string ErrorDetail { set; get; }


    }
    internal class CustomerSignMaterial
    {
        internal bool CallsThirdParty { set; get; }

        internal string Id { set; get; }

        internal string APIUrl { set; get; }

        internal string SaltKey { set; get; }
    }
    public class OuterBusinessService : IBusinessService
    {
        static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
        private OuterHttpClient httpClient = new OuterHttpClient();
        private CustomerSignMaterial signMaterial = null;
        private string CustomerId = string.Empty;
        public OuterBusinessService(string customerId)
        {
            CustomerId = customerId;
            signMaterial = GetSign(customerId);
        }


        async public Task<IdTagInfo> Authorize(string chargeBoxId, string idTag)
        {
            Console.WriteLine(string.Format("Authorize: {0}", CustomerId));
            IdTagInfo result = new IdTagInfo() { status = AuthorizationStatus.Invalid };
            try
            {
               
                string requestParams = string.Format("charging_auth?ChargeBoxId={0}&IdTag={1}", chargeBoxId, idTag);

                if (CustomerId.ToLower() == "9e6bfdcc-09fb-4dab-a428-43fe507600a3")
                {
                    logger.Error(chargeBoxId+" Charging Monitor======================================>");
                    logger.Error(signMaterial.APIUrl + requestParams);
                }
                var response = await httpClient.Post(signMaterial.APIUrl + requestParams, new Dictionary<string, string>()
                            {
                                { "PartnerId",signMaterial.Id}

                            }, null, signMaterial.SaltKey).ConfigureAwait(false);
                if (CustomerId.ToLower() == "9e6bfdcc-09fb-4dab-a428-43fe507600a3")
                {                  
                    logger.Error(JsonConvert.SerializeObject(response));
                }
                if (response.Success)
                {
                    Console.WriteLine(response.Response);
                    var _httpResult = JsonConvert.DeserializeObject<CPOOuterResponse>(response.Response);
                    JObject jo = JObject.Parse(_httpResult.Data);

                    if (jo.ContainsKey("ExpiryDate"))
                    {
                        DateTime dt = jo["ExpiryDate"].Value<DateTime>();
                        result.expiryDate = dt;
                    }

                    if (jo.ContainsKey("ParentIdTag"))
                    {
                        string _Message = jo["ParentIdTag"].Value<string>();
                        result.parentIdTag = _Message;

                    }


                    if (jo.ContainsKey("Status"))
                    {
                        string _Message = jo["Status"].Value<string>();
                        result.status = (AuthorizationStatus)Enum.Parse(typeof(AuthorizationStatus), _Message);
                    }
                }
                else
                {
                    logger.Error(chargeBoxId + " OuterBusinessService.Authorize Fail: " + response.Response);
                }

            }
            catch (Exception ex)
            {
                result.status = AuthorizationStatus.Invalid;

                logger.Error(chargeBoxId + " OuterBusinessService.Authorize Ex: " + ex.ToString());
            }
         
            return result;

        }

        async public Task NotifyFaultStatus(ErrorDetails details)
        {

            try
            {
                if (signMaterial.CallsThirdParty)
                {
                    var response = await httpClient.Post(signMaterial.APIUrl + "connectorfault", new Dictionary<string, string>()
                            {
                                { "PartnerId",signMaterial.Id}

                            }, JsonConvert.SerializeObject(details, GlobalConfig.JSONSERIALIZER_FORMAT), signMaterial.SaltKey).ConfigureAwait(false);


                }


            }
            catch (Exception ex)
            {

                logger.Error(details.ChargeBoxId + " OuterBusinessService.NotifyFaultStatus Ex: " + ex.ToString());
            }


        }

        async public Task NotifyConnectorUnplugged(string chargeBoxId, string transactionId, string timestamp)
        {
            try
            {
                JObject jo = JObject.Parse(transactionId);

                var details = new { ChargeBoxId = chargeBoxId, SessionId = transactionId, Timestamp = timestamp };
                if (signMaterial.CallsThirdParty)
                {
                    var response = await httpClient.Post(signMaterial.APIUrl + "connectorunplugged", new Dictionary<string, string>()
                            {
                                { "PartnerId",signMaterial.Id}

                            }, JsonConvert.SerializeObject(details, new JsonSerializerSettings()
                            {
                                DateTimeZoneHandling = DateTimeZoneHandling.Utc,
                                NullValueHandling = NullValueHandling.Ignore,
                                Formatting = Formatting.None
                            }), signMaterial.SaltKey).ConfigureAwait(false);


                }


            }
            catch (Exception ex)
            {

                logger.Error(chargeBoxId + " OuterBusinessService.NotifyConnectorUnplugged Ex: " + ex.ToString());
            }

        }

        private CustomerSignMaterial GetSign(string customerId)
        {
            Guid Id = new Guid(customerId);
            CustomerSignMaterial _customer = new CustomerSignMaterial();


            using (var db = new MainDBContext())
            {
                _customer = db.Customer.Where(x => x.Id == Id).Select(x => new CustomerSignMaterial() { Id = x.Id.ToString(), APIUrl = x.ApiUrl, SaltKey = x.ApiKey, CallsThirdParty = x.CallPartnerApiOnSchedule }).FirstOrDefault();
            }
            return _customer;
        }

        public Task NotifyConnectorUnplugged(string data)
        {
            throw new NotImplementedException();
        }
    }
}
