using Dapper;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Ocsp;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using XYY.Core.Standard.Data.Infrastructure;
using XYY.Core.Standard.PDF;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using XYY.Service.Standard.ChannelApi.PostNL.Model;
using static NPOI.HSSF.Util.HSSFColor;

namespace XYY.Service.Standard.ChannelApi.PostNL
{
    public class PostNLApi : IBaseApi, IUItidelApi
    {
        public string ServiceName => "NLPost";
        //ILogger<PostNLApi> _logger;
        private IUnitOfWork _unitOfWork;
        public PostNLApi(IUnitOfWork unitOfWork)//Logger<PostNLApi> logger, 
        {
            //_logger = logger;
            _unitOfWork = unitOfWork;
        }


        public async Task<List<BagDeclareErrosResult>> BagDeclare(BagDeclareRequest bagDeclareRequest)
        {
            List<BagDeclareErrosResult> resultList = new List<BagDeclareErrosResult>();
            foreach (var item in bagDeclareRequest.BatchDeclare)
            {
                try
                {
                    await submitData(item.Value, bagDeclareRequest.Channel);
                }
                catch (Exception ex)
                {
                    resultList.Add(new BagDeclareErrosResult() { BoxNumber = item.Key, ErrorMessage = ex.Message });
                }
            }
            return resultList;
        }

        public void CannelOrders(List<string> systemNO)
        {
            throw new NotImplementedException();
        }

        public void CannelOrdersByModel(logistics_ChannelCancel logistics_ChannelCancel)
        {
            throw new NotImplementedException();
        }

        public Task<List<string>> Confims(List<OrderConfimRequest> order, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }
        public Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }
        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            var body = await ConvertRequestBody(order, goods, channel);
            string json = JsonConvert.SerializeObject(body);
            RestClient client = new RestClient(channel.ApiHost + "/v7/api/contentlabel/generate");
            RestRequest request = new RestRequest(Method.POST);
            request.AddHeader("api_key", channel.ApiKey);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = JsonConvert.DeserializeObject<DataUploadResult>(response.Content);
                if (result.status == "success")
                {
                    //_logger.LogError("荷兰邮政小包下单成功:{@Response}", result);
                    var uploadResult = new UploadResult
                    {
                        IsSuccess = true,
                        ServiceOrderNumber = result.data.label_code,
                        ServiceOrderNumber3 = body.product_code,
                        DownloadUrl = result.data.base64string,
                        TrackingNumber = result.data.item,
                    };
                    return uploadResult;
                }
                else
                {
                    throw new Exception($"荷兰邮政小包下单失败:{result.message.payload}");
                }
            }
            else
            {
                throw new Exception($"荷兰邮政小包下单失败:{response.Content ?? response.ErrorMessage}");
            }
        }
        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            var bytes = Convert.FromBase64String(result.DownloadUrl);
            return bytes;
        }
        public async Task<ChannelBagLabelResult> GetChannelBagLabel(ChannelBagLabelParam param)
        {
            GenerateRequestBody body = new GenerateRequestBody();
            string json = JsonConvert.SerializeObject(body);
            RestClient client = new RestClient(param.Channel.ServiceTrackingUrl + "/v7/api/assistlabel/generate");
            RestRequest request = new RestRequest(Method.POST);
            request.AddHeader("api_key", param.Channel.ApiKey);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = JsonConvert.DeserializeObject<GenerateRequestResponse>(response.Content);
                if (result.status == "success")
                {
                    var bytes = Convert.FromBase64String(result.data.assist_labels[0].base64string);
                    var newBytes = PDFHelper.Watermark(bytes, param.Box.BoxNumber, 1, 50, 40, 15, iTextSharp.text.BaseColor.BLACK);
                    var base64 = Convert.ToBase64String(newBytes);

                    ChannelBagLabelResult returnResult = new ChannelBagLabelResult
                    {
                        Label = base64,
                        BoxNumber = param.Box.BoxNumber,
                        ChannelBagNumber = result.data.assist_labels[0].barcode,
                        DestinationPortCode = "",
                        DestinationTurnOverCode = "",
                        ServiceCode = "",
                    };
                    return returnResult;
                }
                else
                {
                    throw new Exception($"荷兰邮政获取大包面单失败:{result.message.payload}");
                }
            }
            else
            {
                throw new Exception($"荷兰邮政，获取大包面单失败,错误状态码:{response.StatusCode},{response.Content}");
            }
        }
        /// <summary>
        /// 这个渠道不需要使用这个方法
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task CannelBag(CannelIBBagParam param) { throw new NotImplementedException(); }

        private async Task<NLRequest> ConvertRequestBody(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel)
        {
            string[] receiverCountryCodes = new string[] {
            "AT",   "BE",   "BG",   "CY",   "DK",   "EE",   "FI",   "FR",   "DE",   "GR",   "HU",   "IE",   "IT",   "LV",   "LT",   "LU",   "MT",   "NL",   "PL",   "PT",   "RO",   "SK",   "SI",   "ES",   "SE",   "HR",   "CZ"
            };
            NLRequest result = new NLRequest();
            var dbResult = (await _unitOfWork.QueryBySqlAsync<Logistics_NLChannelReferenceCode>($"select * from Logistics_NLChannelReferenceCode(nolock)  where CountryCode='{order.ReceiverCountryCode}' ")).ToList();
            string ServiceChannelCode = string.Empty;
            if (channel.PublicCode == "NLLine1-E") { ServiceChannelCode = dbResult.Where(x => !string.IsNullOrEmpty(x.NLLine1E))?.FirstOrDefault()?.NLLine1E; }
            else if (channel.PublicCode == "NLLine1-G") { ServiceChannelCode = dbResult.Where(x => !string.IsNullOrEmpty(x.NLLine1G))?.FirstOrDefault()?.NLLine1G; }
            if (string.IsNullOrEmpty(ServiceChannelCode)) { throw new Exception($"荷兰邮政小包：{channel.PublicCode}，根据收件人国家，获取不到正确的渠道代码，请确认收件人国家是否正确！"); }
            result.product_code = ServiceChannelCode;
            result.customer_reference_number = order.SystemNo;
            result.gross_weight_grams = order.CustomerWeight;
            if (goods.FirstOrDefault().DeclareCurrency == "RNM") { result.currency = "CNY"; }
            if (receiverCountryCodes.Contains(order.ReceiverCountryCode))
            {
                result.currency = "EUR";//荷兰邮政清关必须使用EUR,收件国家为欧洲国家时，直接替换币种
            }
            else
            {
                result.currency = goods.FirstOrDefault().DeclareCurrency;
            }
            result.sender_details = new Sender_details()
            {
                name = channel.SenderName,
                company = channel.SenderCompany,
                address = channel.SenderStreet,
                postal_code = channel.SenderZipCode,
                city = channel.SenderCity,
                state = channel.SenderState,
                country = channel.SenderCounty,
                country_code = channel.SenderCountryCode,
                email = channel.SenderEmail,
                phone = channel.SenderPhone,
                id_ref = order.ioss,//税号 "c#r2cdkffh"
            };
            result.addressee_details = new Addressee_details()
            {
                name = order.ReceiverName,
                address = order.ReceiverStreet,
                postal_code = order.ReceiverZipCode,
                city = order.ReceiverCity,
                country = dbResult.FirstOrDefault().CountryNameEN,
                country_code = order.ReceiverCountryCode,
                phone = order.ReceiverPhone,
            };
            result.content_pieces = new List<Content_piecesItem>();
            foreach (var item in goods)
            {
                Content_piecesItem good = new Content_piecesItem()
                {
                    goods_description = item.EnName,
                    quantity = item.Quantity,
                    total_weight_grams = item.Weight,
                    total_goods_value = item.DeclareFee,
                    total_goods_value_eur = item.DeclareFee,
                    tariff = item.HsCode,
                };
                result.content_pieces.Add(good);
            }

            return result;

        }

        private async Task submitData(List<BoxDetailItem> details, Logistics_Channel channel)
        {
            //原始数据判断
            if (details.Any(x => string.IsNullOrEmpty(x.UserBoxNumber))) { throw new Exception($"箱子：{details.FirstOrDefault().BoxNumber},没有 UserBoxNumber 信息，数据不完整。"); }
            var channelCodes = details.Select(x => x.ServiceOrderNumber3).Distinct().ToList();
            if (channelCodes.Count != 1) { throw new Exception($"箱子：{details.FirstOrDefault().BoxNumber},存在不同渠道产品数据，请联系技术核查！"); }
            //处理api请求数据
            ManifestRequestBody body = new ManifestRequestBody();
            body.assistlabel_item = new Assistlabel_item() { assistlabel = details.FirstOrDefault().UserBoxNumber, product_code = channelCodes.FirstOrDefault(), items = new List<string>(), };
            body.assistlabel_item.items.AddRange(details.Select(x => x.TrackingNumber));
            string json = JsonConvert.SerializeObject(body);
            RestClient client = new RestClient(channel.ServiceTrackingUrl + "/v7/api/label/closeout");
            RestRequest request = new RestRequest(Method.POST);
            request.AddHeader("api_key", channel.ApiKey);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = JsonConvert.DeserializeObject<ManifestRequestResponse>(response.Content);
                if (result.status != "success")
                {
                    throw new Exception($"荷兰邮政预报失败:{result.message.payload}");
                }
            }
            else
            {
                throw new Exception($"荷兰邮政预报失败，错误状态码:{response.StatusCode},{response.Content}");
            }
        }
    }
}
