using FastJSON;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Top.Api;
using XYY.Common.Standard;
using XYY.Data.Standard.FeeCount;
using XYY.Model.Standard.FeeCount;
using static XYY.Common.Standard.QYWXWebHook;

namespace XYY.Service.Standard.Finance
{
    public interface IFinanceFeeCountService
    {

        /// <summary>
        /// 根据订单号获取计费请求参数
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        Task<string> GetFeesQueryParamByOrder(FinanceOrderFeeParam param);

        ///// <summary>
        ///// 请求计费
        ///// </summary>
        ///// <param name="param"></param>
        ///// <returns></returns>

        //Task<FeesQueryResult<CustomerFeeQueryParam>> GetFeesQuery(CustomerFeeQueryParam param);

    }

    public class FinanceFeeCountService : IFinanceFeeCountService
    {

        private readonly IFinance_Express_FeechargesRepository _finance_Express_FeechargesRepository;

        private readonly IOrder_Count_FeeRepository _order_Count_FeeRepository;


        private readonly IOrder_Count_Fee_DetailRepository _order_Count_Fee_DetailRepository;


        public FinanceFeeCountService(IFinance_Express_FeechargesRepository finance_Express_FeechargesRepository, IOrder_Count_FeeRepository order_Count_FeeRepository, IOrder_Count_Fee_DetailRepository order_Count_Fee_DetailRepository)
        {
            this._finance_Express_FeechargesRepository = finance_Express_FeechargesRepository;
            _order_Count_FeeRepository = order_Count_FeeRepository;
            _order_Count_Fee_DetailRepository = order_Count_Fee_DetailRepository;
        }

        private Result<List<FeeQueryResultDto>> GetFeesQuery(CustomerFeeQueryParam param)
        {
            string url = "http://192.168.110.85:8093/api/customerFeeQuery/customerFeeQuery";
            RestClient client = new RestClient(url);
            RestRequest request = new RestRequest(Method.POST);
            request.AddJsonBody(param);
            var response = client.Execute(request);
            if (!response.IsSuccessful)
            {

                throw new Exception("发送费用请求消息失败:" + (response.ErrorMessage ?? response.Content));
            }
            else
            {
                var result = Newtonsoft.Json.JsonConvert.DeserializeObject<Result<List<FeeQueryResultDto>>>(response.Content);
                return result;
            }
        }

        public async Task<string> GetFeesQueryParamByOrder(FinanceOrderFeeParam param)
        {
            string result = string.Empty;
            IEnumerable<ExpressFeechargesModel> expressFeechargesModels = await _finance_Express_FeechargesRepository.GetExpressFeecharges(param.beginDate, param.endDate, param.customerId);
            if (null != expressFeechargesModels && expressFeechargesModels.Count() > 0)
            {
                List<Order_Count_Fee> orderCountFeeList = new List<Order_Count_Fee>();
                List<Order_Count_Fee_Detail> orderCountFeeDetailList = new List<Order_Count_Fee_Detail>();
                Stopwatch feesQueryWatch = new Stopwatch();
                feesQueryWatch.Start();
                foreach (ExpressFeechargesModel item in expressFeechargesModels)
                {

                    CustomerFeeQueryParam customerFeeQueryParam = new CustomerFeeQueryParam();
                    List<string> productIdList = new List<string>();
                    productIdList.Add(item.Publiccode);
                    customerFeeQueryParam.productIdList = productIdList;
                    customerFeeQueryParam.orgId = item.Publiccode;
                    customerFeeQueryParam.customerId = item.CustomerId.ToString();
                    customerFeeQueryParam.feeSetType = FeeSetType.Customer;
                    customerFeeQueryParam.packageType = PackageType.None;
                    customerFeeQueryParam.currentDate = DateTime.Now;
                    DestinationAddressParam destinationAddressParam = new DestinationAddressParam();
                    destinationAddressParam.countryCode = item.CountryCode;
                    destinationAddressParam.zipCode = item.ZipCode;
                    customerFeeQueryParam.destinationAddress = destinationAddressParam;

                    List<WeightVolume> weightVolumeList = new List<WeightVolume>();
                    weightVolumeList.Add(new WeightVolume
                    {
                        weight = decimal.Parse(item.BillingWeight.ToString()),
                        length = item.Length,
                        width = item.Width,
                        height = item.Height,
                    });
                    customerFeeQueryParam.weightVolumeList = weightVolumeList;
                    customerFeeQueryParam.compareCustomsCurrencyCode = null;
                    customerFeeQueryParam.customsFees = 0;
                    customerFeeQueryParam.customsCode = null;
                    customerFeeQueryParam.lightFlag = false;
                    customerFeeQueryParam.weightRatio = 0;
                    customerFeeQueryParam.productNumber = 0;
                    customerFeeQueryParam.customsPageNumber = 0;
                    customerFeeQueryParam.specialPackageNumber = 0;
                    customerFeeQueryParam.feeItemSpecialFlagList = new List<int>();
                    if (item.IsOnline)
                    {
                        customerFeeQueryParam.feeItemSpecialFlagList.Add(30);
                    }

                    string url = @"http://localhost:22707/api/remote/Check";
                    RestClient client = new RestClient(url);
                    RestRequest request = new RestRequest(Method.POST);
                    request.AddJsonBody(new { ExpressId = 22, Postal = item.ZipCode });
                    var response = client.Execute<bool>(request);
                    if (response.ResponseStatus == ResponseStatus.Completed)
                    {
                        if (response.Data)
                        {
                            customerFeeQueryParam.feeItemSpecialFlagList.Add(5);
                        }
                    }
                    try
                    {


                        feesQueryWatch.Restart();
                        Result<List<FeeQueryResultDto>> feesQueryResult = GetFeesQuery(customerFeeQueryParam);
                        long milliseconds = feesQueryWatch.ElapsedMilliseconds;

                        if (null != feesQueryResult && null != feesQueryResult.data && feesQueryResult.data.Count > 0)
                        {
                            foreach (FeeQueryResultDto feeQueryResultDto in feesQueryResult.data)
                            {

                                Order_Count_Fee order_Count_Fee = new Order_Count_Fee();
                                order_Count_Fee.orderFeeId = Guid.NewGuid().ToString();
                                order_Count_Fee.AccountingNo = item.AccountingNo;
                                order_Count_Fee.SystemNo = item.BillNo;
                                order_Count_Fee.TransactionTime = item.TransactionTime;
                                order_Count_Fee.totalFee = feeQueryResultDto.totalFee.Value;
                                order_Count_Fee.CustomerId = item.CustomerId;
                                order_Count_Fee.TrackingNumber = item.TrackingNumber;
                                order_Count_Fee.ChannelId = item.ExpressId;
                                order_Count_Fee.Weight = decimal.Parse(item.BillingWeight.ToString());
                                order_Count_Fee.CountryCode = item.CountryCode;
                                order_Count_Fee.ZipCode = item.ZipCode;
                                order_Count_Fee.Width = item.Width;
                                order_Count_Fee.Length = item.Length;
                                order_Count_Fee.Height = item.Height;
                                order_Count_Fee.CreateTime = DateTime.Now;
                                order_Count_Fee.formulaDescription = feeQueryResultDto.formulaDescription;
                                order_Count_Fee.productName = feeQueryResultDto.productName;
                                order_Count_Fee.countFeeWeight = feeQueryResultDto.countFeeWeight.HasValue ? feeQueryResultDto.countFeeWeight.Value : 0;
                                order_Count_Fee.volumeWeight = feeQueryResultDto.volumeWeight.HasValue ? feeQueryResultDto.volumeWeight.Value : 0;
                                order_Count_Fee.currencyCode = feeQueryResultDto.currencyCode;
                                order_Count_Fee.partitionName = feeQueryResultDto.partitionName;
                                order_Count_Fee.packageType = feeQueryResultDto.packageType.HasValue ? (int)feeQueryResultDto.packageType.Value : 0;
                                orderCountFeeList.Add(order_Count_Fee);
                                if (null != feeQueryResultDto.feeItemDtoList && feeQueryResultDto.feeItemDtoList.Count > 0)
                                {
                                    foreach (FeeItemResultDto feeItemResultDto in feeQueryResultDto.feeItemDtoList)
                                    {
                                        Order_Count_Fee_Detail order_Count_Fee_Detail = new Order_Count_Fee_Detail();
                                        order_Count_Fee_Detail.feeItemId = feeItemResultDto.feeItemId.HasValue ? feeItemResultDto.feeItemId.Value : 0;
                                        order_Count_Fee_Detail.orderFeeId = order_Count_Fee.orderFeeId;
                                        order_Count_Fee_Detail.feeItemName = feeItemResultDto.feeItemName;
                                        order_Count_Fee_Detail.fee = feeItemResultDto.fee.HasValue ? feeItemResultDto.fee.Value : 0;
                                        order_Count_Fee_Detail.exchangeRate = feeItemResultDto.exchangeRate.HasValue ? feeItemResultDto.exchangeRate.Value : 0;
                                        order_Count_Fee_Detail.oriCurrencyFee = feeItemResultDto.oriCurrencyFee.HasValue ? feeItemResultDto.oriCurrencyFee.Value : 0;
                                        order_Count_Fee_Detail.oriCurrencyCode = feeItemResultDto.oriCurrencyCode;
                                        orderCountFeeDetailList.Add(order_Count_Fee_Detail);
                                    }
                                }
                            }
                        }

                    }
                    catch (Exception ex)
                    {
                        string remark = string.Format("订单{0}获取计费失败! 原因{1},请求参数:{2}", item.OrderId, ex.Message, JsonConvert.SerializeObject(customerFeeQueryParam));
                        Order_Count_Fee order_Count_Fee = new Order_Count_Fee();
                        order_Count_Fee.AccountingNo = item.AccountingNo;
                        order_Count_Fee.SystemNo = item.BillNo;
                        order_Count_Fee.TransactionTime = item.TransactionTime;
                        order_Count_Fee.CustomerId = item.CustomerId;
                        order_Count_Fee.TrackingNumber = item.TrackingNumber;
                        order_Count_Fee.ChannelId = item.ExpressId;
                        order_Count_Fee.Weight = decimal.Parse(item.BillingWeight.ToString());
                        order_Count_Fee.CountryCode = item.CountryCode;
                        order_Count_Fee.ZipCode = item.ZipCode;
                        order_Count_Fee.Width = item.Width;
                        order_Count_Fee.Length = item.Length;
                        order_Count_Fee.Height = item.Height;
                        order_Count_Fee.CreateTime = DateTime.Now;
                        order_Count_Fee.remark = remark;
                        orderCountFeeList.Add(order_Count_Fee);
                    }
                }

                feesQueryWatch.Stop();


                try
                {
                    if (orderCountFeeDetailList.Count > 0)
                    {
                        await _order_Count_Fee_DetailRepository.BulkToDBAsync(orderCountFeeDetailList);
                    }

                    if (orderCountFeeList.Count > 0)
                        await _order_Count_FeeRepository.BulkToDBAsync(orderCountFeeList);
                }
                catch (Exception e)
                {
                    throw new Exception("计费失败:" + e.Message);
                }
            }
            return result;
        }
    }
}
