using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Core.Standard.Data.Infrastructure;
using XYY.Model.Standard.Logistics;
using Dapper;
using XYY.Model.Standard.Dto.Logistics;
using XYY.Common.Standard;

namespace XYY.Service.Standard.Order
{
    #region Iservices
    public interface IHSCodeService
    {
        Task<List<logistics_EUHSCode>> InsEUHSCode(string code);
        Task<List<EUHSCodeDto>> GetEUHSCodeDtos(List<int> Ids);
        Task<List<logistics_EUHSCode>> GetEUHSCode(List<string> TwoCodes);
        Task<bool> SaveEUHSCodeUpdate(List<EUHSCodeDto> dtos, UserContent user);
    }
    #endregion
    #region services

    public class HSCodeService : IHSCodeService
    {
        IUnitOfWork _unitOfWork;
        public HSCodeService(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        public async Task<List<logistics_EUHSCode>> InsEUHSCode(string code)
        {
            try
            {
                string json = await GetDataByEU(code);
                var data = await AnalyseDataByEU(json);
                List<logistics_EUHSCode> eUHSCodes = await ConvertToEUHSCode(data);
                if (eUHSCodes != null && eUHSCodes.Count > 0)
                {
                    List<string> twoCodes = eUHSCodes.Select(x => x.TwoCode).Distinct().ToList();
                    await _unitOfWork.ExecuteAsync("delete logistics_EUHSCode where TwoCode in @TwoCode", new { TwoCode = twoCodes });
                    await _unitOfWork.BulkToDBAsync(eUHSCodes);
                    return eUHSCodes;
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

        #region 外部请求与解析操作

        #region 欧盟海关编码
        private async Task<string> GetDataByEU(string code)
        {
            string result = string.Empty;
            try
            {
                string QueryCode = code.Substring(0, 2);
                string TimeStr = DateTime.Now.ToString("yyyyMMdd");
                var client = new RestClient($"https://ec.europa.eu/taxation_customs/dds2/taric/nomenclaturetree/nomenclaturetree_zh_{TimeStr}_{QueryCode}_zh.js");
                client.Timeout = -1;
                var request = new RestRequest(Method.GET);
                request.AddHeader("Cookie", "JSESSIONID=JgfZEqhLcAXhSk9b6dKhfX99rN0TkVRSpzB1BGb10X3bjY3Dhgon!1692863140");
                IRestResponse response = await client.ExecuteAsync(request);
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    string content = response.Content;
                    content = content.Substring(content.IndexOf("chaptertree = ") + "chaptertree = ".Length - 1);
                    result = content.Trim(';');
                }
            }
            catch (Exception ex)
            {
                //忽略异常
                result = string.Empty;
            }
            return result;
        }
        private async Task<Dictionary<string, string>> AnalyseDataByEU(string josnStr)
        {
            JArray json = JArray.Parse(josnStr);
            Dictionary<string, string> result = new Dictionary<string, string>();
            result = AnalysisJsonByEU(json, result);
            return result;
        }
        private Dictionary<string, string> AnalysisJsonByEU(JToken JArry, Dictionary<string, string> result)
        {
            foreach (var item in JArry)
            {
                if (item[7] != null && !string.IsNullOrEmpty(item[7].ToString()))
                {
                    AnalysisJsonByEU(item[7], result);
                }
                else
                {
                    result.Add(item[2].ToString(), item[5].ToString());
                }
            }
            return result;//输出解析后的数据
        }
        private async Task<List<logistics_EUHSCode>> ConvertToEUHSCode(Dictionary<string, string> dic)
        {
            List<logistics_EUHSCode> codes = new List<logistics_EUHSCode>();
            DateTime date = DateTime.Now.Date;
            foreach (var item in dic)
            {
                codes.Add(new logistics_EUHSCode()
                {
                    TwoCode = item.Key.Substring(0, 2),
                    SixCode = item.Key.Substring(0, 6),
                    HSCode = item.Key,
                    CodeDescription = item.Value,
                    SyncDate = date.Date,
                    CreateTime = DateTime.Now,
                });
            }
            return codes;
        }
        #endregion

        #endregion
        public async Task<List<EUHSCodeDto>> GetEUHSCodeDtos(List<int> Ids)
        {
            List<EUHSCodeDto> dtos = new List<EUHSCodeDto>();
            string sql = @"select b.Id,b.MpsOrderId,b.EnName,b.CnName,b.HsCode,a.CustomerOrderNumber,left(b.HsCode,2)TwoCode,left(b.HsCode,6)SixCode from Order_MpsOrder(nolock) a
left join Order_MpsOrderGoods(nolock) b on b.MpsOrderId=a.Id
where a.OrderId in @OrderId";
            var mappings = (await _unitOfWork.QueryBySqlAsync<MpsOrderGoodsMapping>(sql, null, new { OrderId = Ids })).ToList();
            if (mappings.Count == 0) { throw new Exception("未获取到任何一票多件商品！"); }
            var baseDto = mappings.Select(x => new { x.MpsOrderId, x.CustomerOrderNumber }).Distinct().ToList();
            //取所有的两位码
            List<string> TwoCodes = mappings.Select(x => x.TwoCode).Distinct().ToList();
            List<logistics_EUHSCode> dbCodes = await GetEUHSCode(TwoCodes);
            //List<string> SixCodes = mappings.Select(x => x.SixCode).Distinct().ToList();
            foreach (var item in baseDto)
            {
                var tempEUHSCodeDto = new EUHSCodeDto();
                tempEUHSCodeDto.MpsOrderId = item.MpsOrderId;
                tempEUHSCodeDto.CustomerOrderNumber = item.CustomerOrderNumber;
                tempEUHSCodeDto.mappings = mappings.Where(x => x.MpsOrderId == item.MpsOrderId).ToList();
                //执行获取与匹配
                foreach (var good in tempEUHSCodeDto.mappings)
                {
                    //海关编码匹配
                    good.EUHSCodes = dbCodes.Where(x => x.SixCode == good.SixCode).ToList();
                    if (good.EUHSCodes == null || good.EUHSCodes.Count == 0)
                    {
                        good.EUHSCodes = dbCodes.Where(x => x.TwoCode == good.TwoCode).ToList();
                    }
                    good.EUHSCode = good.EUHSCodes.FirstOrDefault().HSCode;
                }
                dtos.Add(tempEUHSCodeDto);
            }
            return dtos;
        }
        public async Task<List<logistics_EUHSCode>> GetEUHSCode(List<string> TwoCodes)
        {
            bool IsSucces = true; string message = "头两位数字为以下数字的商品，无法有效获取欧盟海关编码！";
            string sql = @"select [Id]
      ,[CreateUserName]
      ,[CreateTime]
      ,[UpdateUserName]
      ,[UpdateTime]
      ,[Remark]
      ,[TwoCode]
      ,[SixCode]
      ,[HSCode]
      ,[SyncDate]
      ,left([CodeDescription],200) [CodeDescription] from logistics_EUHSCode where TwoCode in @TwoCodes";
            List<logistics_EUHSCode> eUHSCodes = (await _unitOfWork.QueryBySqlAsync<logistics_EUHSCode>(sql, null, new { TwoCodes = TwoCodes })).ToList();
            var dbTwoCodes = eUHSCodes.Select(x => x.TwoCode).Distinct().ToList();
            if (dbTwoCodes.Count() != TwoCodes.Count)
            {
                List<string> differenceCode = TwoCodes.Where(x => !dbTwoCodes.Contains(x)).ToList();
                foreach (var item in differenceCode)
                {
                    var codes = await InsEUHSCode(item);
                    if (codes != null) { eUHSCodes.AddRange(codes); } else { IsSucces = false; message += $"[{item}]"; }
                }
            }
            //判断取值过程中是否存在异常，异常抛出
            if (IsSucces)
            {
                return eUHSCodes;
            }
            else
            {
                throw new Exception(message);
            }
        }
        public async Task<bool> SaveEUHSCodeUpdate(List<EUHSCodeDto> dtos, UserContent user)
        {
            bool result = true;
            //获取待更新数据
            var waitUpdate=dtos.SelectMany(x=>x.mappings.Where(y=>y.IsUpdate)).ToList();
            if (waitUpdate==null||waitUpdate.Count==0) { return result; }
            //20个订单 每个50个产品  也才1000条数据
            try
            {
                string sql = $" update Order_MpsOrderGoods set HsCode=@EUHSCode,UpdateTime=GETDATE(),UpdateUserName='{user.NiceName}' where Id=@Id ";
                await _unitOfWork.ExecuteAsync(sql, waitUpdate);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return result;
        }
    }
    #endregion
}
