using AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Models;
using AlibabaCloud.SDK.Dingtalkservice_group_1_0.Models;
using Aliyun.Credentials.Http;
using Dapper;
using EasyNetQ.Internals;
using HtmlAgilityPack;
using iTextSharp.text;
using Nest;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Edge;
using Org.BouncyCastle.Ocsp;
using RestSharp;
using ScrapySharp.Extensions;
using ScrapySharp.Html;
using ScrapySharp.Network;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Permissions;
using System.Security.Policy;
using System.Threading;
using System.Threading.Tasks;
using XYY.Core.Standard.Data.Infrastructure;
using static XYY.Data.Standard.Finance.Finance_Customer_SupplementRepository;

namespace XYY.Service.Standard.Finance
{
    public interface IExpressageThirdPartyDataService
    {
        Task<Tuple<bool, string>> FedexSurchargesSync();
        Task<Tuple<bool, string>> DHLSurchargesSync();
    }
    public class ExpressageThirdPartyDataService : IExpressageThirdPartyDataService
    {
        private IUnitOfWork _unitOfWork;

        public ExpressageThirdPartyDataService(IUnitOfWork unitOfWork
            )
        {
            _unitOfWork = unitOfWork;
        }

        #region XYY业务
        public async Task<Tuple<bool, string>> FedexSurchargesSync()
        {
            bool isSuccess = true; string flowMsg = string.Empty;
            try
            {
                flowMsg += "\r\n-->fedex准备获取数据";
                Tuple<string, string> originalData = await GetFedexSurcharges();
                flowMsg += "\r\n-->fedex获取数据成功";
                Logistics_Fee_Other other = ConvertToFeeOther(originalData.Item1, originalData.Item2, ThirdPartyDataSoure.fedex);
                flowMsg += "\r\n-->fedex转换数据成功";
                var dbData = await GetFeeOther(other.EffectiveDate.ToString(), ThirdPartyDataSoure.fedex);
                if (dbData != null) { flowMsg += $"\r\n-->fedex燃油费已是最新版。{dbData.EffectiveDate.ToString()}"; return Tuple.Create<bool, string>(isSuccess, flowMsg); }
                await _unitOfWork.InsertAsync(other);
                var client = new RestClient("http://120.24.149.148:9503/api/RedisCacheMange/RefreshOtherRedisCache?customerId=0&expressId=48");
                client.Timeout = -1;
                var request = new RestRequest(Method.POST);
                request.AddHeader("Authorization", "token 132A7468DE079C6CEB59F383A661E612");
                IRestResponse response = client.Execute(request);
                flowMsg += $"\r\n-->fedex缓存刷新。{JsonConvert.DeserializeObject<dynamic>(response.Content).message}";
                flowMsg += $"\r\n-->fedex同步最新记录完成。{other.EffectiveDate.ToString()}";
            }
            catch (Exception ex)
            {
                isSuccess = false; flowMsg += "\r\n-->发生错误：" + ex.Message;
            }
            return Tuple.Create<bool, string>(isSuccess, flowMsg);
        }
        public async Task<Tuple<bool, string>> DHLSurchargesSync()
        {
            bool isSuccess = true; string flowMsg = string.Empty;
            try
            {
                flowMsg += "\r\n-->dhl准备获取数据";
                Tuple<string, string> originalData = await GetDHLSurcharges();
                flowMsg += "\r\n-->dhl获取数据成功";
                Logistics_Fee_Other other = ConvertToFeeOther(originalData.Item1, originalData.Item2, ThirdPartyDataSoure.dhl);
                flowMsg += "\r\n-->dhl转换数据成功";
                var dbData = await GetFeeOther(other.EffectiveDate.ToString(), ThirdPartyDataSoure.dhl);
                if (dbData != null) { flowMsg += $"\r\n-->dhl燃油费已是最新版。{dbData.EffectiveDate.ToString()}"; return Tuple.Create<bool, string>(isSuccess, flowMsg); }
                await _unitOfWork.InsertAsync(other);
                var client = new RestClient("http://120.24.149.148:9503/api/RedisCacheMange/RefreshOtherRedisCache?customerId=0&expressId=50");
                client.Timeout = -1;
                var request = new RestRequest(Method.POST);
                request.AddHeader("Authorization", "token 132A7468DE079C6CEB59F383A661E612");
                IRestResponse response = client.Execute(request);
                flowMsg += $"\r\n-->dhl缓存刷新。{JsonConvert.DeserializeObject<dynamic>(response.Content).message}";
                flowMsg += $"\r\n-->dhl同步最新记录完成。{other.EffectiveDate.ToString()}";
            }
            catch (Exception ex)
            {
                isSuccess = false; flowMsg += "\r\n-->发生错误：" + ex.Message;
            }
            return Tuple.Create<bool, string>(isSuccess, flowMsg);
        }

        public async Task<Logistics_Fee_Other> GetFeeOther(string EffectiveDate, ThirdPartyDataSoure soure)
        {
            string sql = @$"select top 1 *from Logistics_Fee_Other where CustomerId=0 and FeeType=2 and ExpressId={(int)soure} and EffectiveDate='{EffectiveDate}'
order by EffectiveDate desc ";
            return (await _unitOfWork.QueryBySqlAsync<Logistics_Fee_Other>(sql))?.FirstOrDefault();
        }
        #endregion

        #region 第三方源数据获取
        private async Task<Tuple<string, string>> GetFedexSurcharges()
        {
            var uri = new Uri("https://www.fedex.com/zh-cn/shipping/surcharges.html");
            #region 保留对比，访问成功
            //HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(uri);
            //myReq.Method = "GET";
            //myReq.Accept = "*/*";
            //myReq.Headers.Add("Accept-Language", "zh-CN,zh;q=0.9");
            //myReq.UserAgent = "PostmanRuntime/7.29.2";

            //HttpWebResponse result = (HttpWebResponse)myReq.GetResponse();
            //var stream = result.GetResponseStream();
            //string responsestr = string.Empty;
            //using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.Default))
            //{
            //    responsestr = reader.ReadToEnd();
            //    stream.Dispose();
            //}
            #endregion
            #region 保留，仅本地测试生效
            //var browser1 = new ScrapingBrowser();
            ////三行设置，少一个都请求失败
            //browser1.KeepAlive = true;
            //browser1.Headers.Add("Accept", "*/*");
            //browser1.UserAgent = new FakeUserAgent("", "PostmanRuntime/7.29.2");
            //var html1 = browser1.DownloadString(uri);
            //html1 = selenium.PageSource;
            //var htmlDocument = new HtmlDocument();
            //htmlDocument.LoadHtml(html1);
            //var html = htmlDocument.DocumentNode;

            //var div = html.CssSelect("div.js-dy-fsc-init>div.fxg-dy-fsc__content");//只取第一个数据
            //var childerDiv = div.CssSelect("div");
            //List<string> text = childerDiv.Select(x => x.InnerText).ToList();
            #endregion

            IWebDriver selenium = new EdgeDriver();
            //考虑到120 比较拉胯，3分钟超时 没效果
            //selenium.Manage().Timeouts().PageLoad=new TimeSpan(0,3,0);
            selenium.Navigate().GoToUrl(uri);
            Thread.Sleep(4000);//强制等待 页面加载
            var element = selenium.FindElements(OpenQA.Selenium.By.Id("details-button"));
            if (element!=null&& element.Count>0)
            {
                selenium.FindElement(OpenQA.Selenium.By.Id("details-button")).Click();
                selenium.FindElement(OpenQA.Selenium.By.Id("proceed-link")).Click();
                Thread.Sleep(3000);//强制等待 页面加载
            }
            var div = selenium.FindElement(OpenQA.Selenium.By.CssSelector("div.js-dy-fsc-init>div.fxg-dy-fsc__content"));
            var childerDiv = div.FindElements(OpenQA.Selenium.By.TagName("div"));
            List<string> text = childerDiv.Select(x => x.Text).ToList();
            //必须退出
            selenium.Quit();
            //时间，百分比
            return Tuple.Create<string, string>(text[0], text[2]);
        }
        private async Task<Tuple<string, string>> GetDHLSurcharges()
        {
            #region 纯Xpath 不够灵活

            //var html = @"https://mydhlplus.dhl.com/cn/zh/ship/surcharges.html";
            //HtmlWeb web = new HtmlWeb();
            //var htmlDoc = web.Load(html);

            //var time = htmlDoc.DocumentNode.SelectSingleNode("//*[@id=\"fuel_surcharge\"]/div/div/div/div[2]/div/div/div/div/div/div[2]/table/tbody[2]/tr[1]/td[1]/div/div").InnerText;
            //var free = htmlDoc.DocumentNode.SelectSingleNode("//*[@id=\"fuel_surcharge\"]/div/div/div/div[2]/div/div/div/div/div/div[2]/table/tbody[2]/tr[1]/td[2]/div/div").InnerText;
            #endregion
            var uri = new Uri("https://mydhlplus.dhl.com/cn/zh/ship/surcharges.html#/fuel_surcharge");
            var browser1 = new ScrapingBrowser();

            var html1 = browser1.DownloadString(uri);
            var htmlDocument = new HtmlDocument();
            htmlDocument.LoadHtml(html1);
            var html = htmlDocument.DocumentNode;

            //样式取第二个
            var table = html.CssSelect("table.dhl-tables-component_header-font-style--bold").Skip(1).Take(1);
            var tbody = table.CssSelect("tbody.dhl-tables-component__main-body");
            var tr = tbody.CssSelect("tr");
            var divs = tr.CssSelect(".v2-p");
            List<string> text = divs.Select(x => x.InnerText).ToList();

            //取最新的，只取前两条就行了 
            return Tuple.Create<string, string>(text[0], text[1]);
        }
        #endregion
        #region 格式化数据
        private Logistics_Fee_Other ConvertToFeeOther(string time, string fee, ThirdPartyDataSoure source)
        {
            decimal xyyFee = Convert.ToDecimal(fee.Trim().Replace("%", "")) / 100m;
            Logistics_Fee_Other fee_Other = new Logistics_Fee_Other()
            {
                ExpressId = (int)source,
                FeeType = 2,//2是燃油  写死
                IsEffective = true,
                IsPercentByCodHandCost = true,
                CustomerId = 0,//通用 写死
                CreateTime = DateTime.Now,
                Remark = "系统自动抓取",
                Price = xyyFee,
                EffectiveDate = ConvertToDate(time, source),
            };
            return fee_Other;
        }
        private DateTime ConvertToDate(string Time, ThirdPartyDataSoure source)
        {
            string date = string.Empty;
            switch (source)
            {
                case ThirdPartyDataSoure.fedex:
                    date = FedexTimeToDate(Time);
                    break;
                case ThirdPartyDataSoure.dhl:
                    date = DhlTimeToDate(Time);
                    break;
            }
            return Convert.ToDateTime(date);
        }
        private string FedexTimeToDate(string Time)
        {
            string date = string.Empty;
            List<string> times = Time.Trim().Split("-").ToList();
            string startTime = times[0];
            date = Convert.ToDateTime(startTime).ToString("yyyy-MM-dd");
            return date;
        }
        private string DhlTimeToDate(string Time)
        {
            string date = string.Empty;
            List<string> times = Time.Trim().Split(" ").ToList();
            string startTime = "01 " + ConvertToChineseNum(Convert.ToInt32(times[0].Trim())) + times[1].Trim() + "," + times[2].Trim();
            date = Convert.ToDateTime(startTime).ToString("yyyy-MM-dd");
            return date;
        }
        private string ConvertToChineseNum(int num)
        {
            string ChineseNum = string.Empty;
            switch (num)
            {
                case 1:
                    ChineseNum = "一";
                    break;
                case 2:
                    ChineseNum = "二";
                    break;
                case 3:
                    ChineseNum = "三";
                    break;
                case 4:
                    ChineseNum = "四";
                    break;
                case 5:
                    ChineseNum = "五";
                    break;
                case 6:
                    ChineseNum = "六";
                    break;
                case 7:
                    ChineseNum = "七";
                    break;
                case 8:
                    ChineseNum = "八";
                    break;
                case 9:
                    ChineseNum = "九";
                    break;
                case 10:
                    ChineseNum = "十";
                    break;
                case 11:
                    ChineseNum = "十一";
                    break;
                case 12:
                    ChineseNum = "十二";
                    break;
            }
            return ChineseNum;
        }
        #endregion
    }
    /// <summary>
    /// 枚举值等于渠道Id
    /// </summary>
    public enum ThirdPartyDataSoure
    {
        fedex = 48,
        dhl = 50,
    }
}
