using dodohold.core;
using Org.BouncyCastle.Ocsp;
using System.Net;
using System.Text.Json;
using System.Xml;
using TencentCloud.Lighthouse.V20200324.Models;
using TencentCloud.Weilingwith.V20230427.Models;
using Top.Api;
using Top.Api.Request;
using Top.Api.Response;


namespace molilian.core
{
    public partial class TaobaoOpenPlus
    {
        public enum RecommendRequestType
        {
            first,
            second,
            ori,
        }


        string _app_key = string.Empty;
        string _app_secret = string.Empty;
        string _pid = string.Empty;
        string _server_url = "https://eco.taobao.com/router/rest";
        bool _debug = false;
        public TaobaoOpenPlus(string app_key, string app_secret, string pid, bool debug)
        {
            _app_key = app_key;
            _app_secret = app_secret;
            _pid = pid;
            _debug = debug;
        }

        public static PromotionQueryItemDTO ConverPromotionQueryItem(JsonElement item)
        {
            PromotionQueryItemDTO result = JsonSerializer.Deserialize<PromotionQueryItemDTO>(item.GetRawText());

            string h5_url = item.Read("couponShareUrl", string.Empty);
            if (string.IsNullOrEmpty(h5_url))
            {
                h5_url = item.Read("url", string.Empty);
            }
            if (h5_url.StartsWith("//")) h5_url = "https:" + h5_url;
            result.h5_url = h5_url;
            result.deeplink_url = AlimamaPlus.GetDeeplink(h5_url);

            if (result.pic.StartsWith("//")) result.pic = "https:" + result.pic;
            return result;
        }



        public TbkThorMfrsPromotionQueryResponse PromotionQueryRequest(string base64, string oaid)
        {
            ITopClient client = new DefaultTopClient(_server_url, _app_key, _app_secret, "json");
            TbkThorMfrsPromotionQueryRequest req = new();
            TbkThorMfrsPromotionQueryRequest.ManufacturerLaunchOptionDomain obj1 = new()
            {
                Img = base64,
                Pid = _pid,
                UniqueId = oaid,
                UniqueIdType = "oaid",
                SceneCode = "h5_img",
                SceneSubCode = "Hitoch"
            };
            req.Option_ = obj1;

            TbkThorMfrsPromotionQueryResponse rsp = client.Execute(req);
            if (_debug)
            {
                var _req = req.Convert2Json();
                var _rsp = rsp.Convert2Json();
                new LoggerLibrary("debug", oaid).Info(_req, _rsp).Save();
            }
            return rsp;
        }



        public async Task<(List<PromotionQueryItemDTO>, string, int)> GetRecommendDataWithRetry(
            RecommendRequestType type, string oaid,
            string cookies,
            CancellationToken cancellationToken = default)
        {
            DateTime stime = DateTime.Now;
            // 假设传入了一个 CancellationToken cancellationToken 和 int maxRetries 表示最大重试次数
            int retryCount = 0;
            int maxRetries = 50;
            while (true)
            {
                try
                {
                    (var data, cookies) = await GetRecommendData(type, oaid, cookies, cancellationToken);
                    var ts = DateTime.Now - stime;
                    int elapsedTime = (int)ts.TotalMilliseconds;
                    return (data, cookies, elapsedTime);
                }
                catch (Exception ex)
                {
                    if (type == RecommendRequestType.first &&
                        ex.Message.Equals("RECOMMEND_UNKNOWN_ERROR::Recommend未知错误"))
                    {
                        return (new List<PromotionQueryItemDTO>(), cookies, 2);
                    }
                    if (retryCount >= maxRetries || cancellationToken.IsCancellationRequested)
                    {
                        throw;
                    }
                    retryCount++;
                    Thread.Sleep(100);
                }
            }

        }


        public async Task<(List<PromotionQueryItemDTO>, string)> GetRecommendData(RecommendRequestType type, string oaid,
           string cookies, CancellationToken cancellationToken = default)
        {
            string token = "undefined";
            if (!string.IsNullOrEmpty(cookies)) token = cookies.GetContentPart("_m_h5_tk=", "_");
            string url = GetRecommendUrl(_pid, oaid, token, type);
            string body = string.Empty;

            if (string.IsNullOrEmpty(cookies))
            {
                var res = await new WebClientUtility().RequestAsync(url, "GET", cancellationToken);

                if (!res.Successed) { throw res.ResponseException; }
                body = res.Body();

                if (_debug)
                {
                    new LoggerLibrary("debug", oaid)
                        .Info("第一次 cookies 初始化")
                        .Info(url, body)
                        .Save();
                }

                cookies = res.ResponseMessage.GetCookiesString();
                token = cookies.GetContentPart("_m_h5_tk=", "_");
            }
            url = GetRecommendUrl(_pid, oaid, token, type);

            WebClientUtility client = new WebClientUtility();
            if (!string.IsNullOrEmpty(cookies)) client.SetCookies(cookies);
            var response = await client.RequestAsync(url, "GET", cancellationToken);
            body = response.Body();

            if (_debug)
            {
                new LoggerLibrary("debug", oaid)
                    .Info("GetRecommendData")
                    .Info(url, cookies)
                    .Info(body)
                    .Save();
            }

            body = body.Trim().StringTrimStart("mtopjsonp1(");
            body = body.StringTrimEnd(")");


            var root = body.Convert2JsonElement();
            var ret = root.PathRead("ret[0]", string.Empty);

            if (!"SUCCESS::调用成功".Equals(ret))
            {
                throw new Exception(ret);
            }

            var resultList = new List<PromotionQueryItemDTO>();
            foreach (var data in root.ElementRead("data").ElementRead("resultList").EnumerateArray())
            {
                PromotionQueryItemDTO item = ConverPromotionQueryItem(data);
                resultList.Add(item);
            }
            return (resultList, cookies);
        }


        public string GetRecommendUrl(string pid, string oaid, string token, RecommendRequestType type)
        {
            var first_data = $"{{\"scene\":\"pltSimilarPromotion\",\"variableMap\":\"{{\\\"pid\\\":\\\"{pid}\\\",\\\"oaid\\\":\\\"{oaid}\\\",\\\"type\\\":\\\"first\\\"}}\"}}";
            var second_data = $"{{\"scene\":\"pltSimilarPromotion\",\"variableMap\":\"{{\\\"pid\\\":\\\"{pid}\\\",\\\"oaid\\\":\\\"{oaid}\\\",\\\"type\\\":\\\"second\\\"}}\"}}";
            var ori_data = $"{{\"scene\":\"pltPromotionImg\",\"variableMap\":\"{{\\\"pid\\\":\\\"{pid}\\\",\\\"oaid\\\":\\\"{oaid}\\\",\\\"hasCoupon\\\":false,\\\"filterType\\\":\\\"ori\\\",\\\"seq\\\":\\\"\\\"}}\"}}";

            string ts = DateTime.Now.Convert2UnixTimestamp(true).ToString();
            string data = type switch
            {
                RecommendRequestType.first => first_data,
                RecommendRequestType.second => second_data,
                _ => ori_data,
            };
            string sign = GetSign(token, ts, data);

            string url = $"https://h5api.m.taobao.com/h5/mtop.union.thor.landing.page.recommend/1.0/" +
                $"?jsv=2.4.16&appKey=12574478&t={ts}&sign={sign}&v=1.0&api=mtop.union.thor.landing.page.recommend" +
                $"&timeout=20000&AntiCreep=true&AntiFlood=true&type=jsonp&dataType=jsonp&callback=mtopjsonp1" +
                $"&data={data.UrlEncode()}";

            return url;
        }
        private string GetSign(string token, string ts, string data)
        {
            string g = "12574478";

            //%7B%22scene%22%3A%22pltPromotionImg%22%2C%22variableMap%22%3A%22%7B%5C%22pid%5C%22%3A%5C%22mm_5993059531_3080100059_115689750259%5C%22%2C%5C%22oaid%5C%22%3A%5C%22-7775661578900138800%5C%22%2C%5C%22hasCoupon%5C%22%3Afalse%2C%5C%22filterType%5C%22%3A%5C%22ori%5C%22%2C%5C%22seq%5C%22%3A%5C%22%5C%22%7D%22%7D
            //%7B%22scene%22%3A%22pltPromotionImg%22%2C%22variableMap%22%3A%22%7B%5C%22pid%5C%22%3A%5C%22mm_5993059531_3080100059_115689750259%5C%22%2C%5C%22oaid%5C%22%3A%5C%22-7775661578900138800%5C%22%2C%5C%22hasCoupon%5C%22%3Afalse%2C%5C%22filterType%5C%22%3A%5C%22ori%5C%22%2C%5C%22seq%5C%22%3A%5C%22%5C%22%7D%22%7D


            var signString = $"{token}&{ts}&{g}&{data}";
            return signString.MD5();
        }
    }
}

