package cn.van333.mt2ql.wxMessage.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static cn.hutool.core.thread.ThreadUtil.sleep;

/**
 * @author Leo
 * @version 1.0
 * @create 2023/12/22 0022 上午 09:59
 * @description：
 */
@Component
public class QLUtil {
    /**
     * 1. 在系统设置 -> 应用设置 -> 添加应用，权限目前支持5个模块，可以选择多个模块。选择一个模块之后，可读写此模块的所有接口。
     * 2. 使用生成的 client_id 和 client_secret 请求获取token接口 http://localhost:5700/open/auth/token?client_id=xxxxxx&client_secret=xxxxxxxx
     * 3. 上面接口返回的token有效期为30天，可用于请求青龙的接口 curl 'http://localhost:5700/open/envs?searchValue=&t=1630032278171' -H 'Authorization: Bearer
     * 接口返回的token'
     * 4. openapi的接口与系统正常接口的区别就是青龙里的是/api/envs，openapi是/open/envs，即就是青龙接口中的api换成open
     */
    public static String QL_BASE_URL = "http://134.175.126.60:45700";
    public static final String GET_TOKEN = QL_BASE_URL + "/open/auth/token";

    // /open/envs
    public static final String GET_ENV = QL_BASE_URL + "/open/envs";
    // /open/crons
    public static final String GET_CRON = QL_BASE_URL + "/open/crons";

    //client_id
    public static final String CLIENT_ID = "Ouv_S9gk5LpV";
    //client_secret
    public static final String CLIENT_SECRET = "1pLjAIfBBzu1_UA9q-hOj778";
    public static final String QL_TOKEN_KEY = "QL_TOKEN_KEY";

    private static final RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
    private static final Logger logger = LoggerFactory.getLogger(QLUtil.class);

    private Environment env;

    public QLUtil(Environment env) {
        this.env = env;
        QL_BASE_URL = env.getProperty("config.QL_BASE_URL");
    }

    public String getToken() {

        String token = null;
        token = redisCache.getCacheObject(QL_TOKEN_KEY);
        if (StrUtil.isNotEmpty(token)) {

        } else {
            //HashMap<String, String> map = new HashMap<>();
            //map.put("client_id", CLIENT_ID);
            //map.put("client_secret", CLIENT_SECRET);
            //String jsonStr = JSON.toJSONString(map);
            while (Util.isNotEmpty(token)) {
                //* 2. 使用生成的 client_id 和 client_secret 请求获取token接口 http://localhost:5700/open/auth/token?client_id=xxxxxx&client_secret=xxxxxxxx
                String responseStr = HttpRequest.get(GET_TOKEN + "?client_id=" + CLIENT_ID + "&client_secret=" + CLIENT_SECRET).execute().body();
                if (ObjectUtil.isNotEmpty(responseStr)) {
                    //{"code":200,"data":{"token":"950e3060-d714-4f6a-9839-c098a116f0a8","token_type":"Bearer","expiration":1705743778}}
                    JSONObject jsonObject = JSON.parseObject(responseStr);
                    if (Objects.equals(String.valueOf(jsonObject.getString("code")), "200")) {
                        JSONObject response = jsonObject.getJSONObject("data");
                        redisCache.setCacheObject(QL_TOKEN_KEY, (String) response.get("token"), (int) response.get("expiration"), TimeUnit.SECONDS);
                        token = (String) response.get("token");
                    }
                }
                sleep(500);
            }
        }
        return token;
    }


    // get /envs

    /**
     * @return
     * @throws
     * @description 获取所有环境变量
     */
    public JSONArray getEnv(String searchKey) {
        String token = getToken();
        JSONArray result = new JSONArray();
        int maxRetryCount = 3;
        int retryCount = 0;
        String getUrl = GET_ENV + "?searchValue=&t=1630032278171";
        if (Util.isNotEmpty(searchKey)) {
            getUrl = GET_ENV + "?searchValue=" + searchKey + "&t=1630032278171";
        }
        while (result.size() == 0 && retryCount < maxRetryCount) {

            String responseStr = HttpRequest.get(getUrl).header("Authorization", "Bearer " + token).execute().body();
            if (ObjectUtil.isNotEmpty(responseStr)) {
                JSONObject qlResponse = JSONObject.parseObject(responseStr);
                if (qlResponse.getString("code").equals("200")) {

                    result = (JSONArray) qlResponse.get("data");
                    //result = null;
                }
            }
            retryCount++;
            sleep(1000);
        }
        return result;
    }

    /**
     * @param name
     * @return
     * @throws
     * @description 检查是否存在环境变量，存在返回值，不存在返回null
     */
    //public String getEnvValue(String name) {
    //    JSONObject jsonObject = getEnv();
    //    if (ObjectUtil.isNotEmpty(jsonObject)) {
    //        return jsonObject.getJSONObject(name).getString("value");
    //    }
    //    return null;
    //}

    // post /envs
    // {
    //    "value": "123",
    //    "name": "test_add",
    //    "remarks": "新建测试"
    //}

    /**
     * @param name
     * @param remarks
     * @param value
     * @return
     * @throws
     * @description 添加环境变量 name 环境变量名，value 环境变量值，remarks 环境变量备注
     * 如果存在一样的value 会返回 400
     * 如果添加成功，就返回 TRUE ，否则返回 FALSE
     */
    public Boolean addEnv(String value, String name, String remarks) {
        String token = getToken();
        JSONObject result = new JSONObject();
        List<QLEnv> bodyArr = Collections.singletonList(new QLEnv(value, name, remarks));
        logger.info("addEnv 请求body {}", JSON.toJSONString(bodyArr));

        // 设置最大重试次数
        int maxRetryCount = 3;
        int retryCount = 0;

        while (Util.isEmpty(result) && retryCount < maxRetryCount) {
            String responseStr = HttpRequest.post(GET_ENV)
                    .header("Authorization", "Bearer " + token)
                    .body(JSON.toJSONString(bodyArr))
                    .execute()
                    .body();
            logger.info("responseStr 响应 {}", responseStr);

            if (Util.isNotEmpty(responseStr)) {
                JSONObject qlResponse = JSONObject.parseObject(responseStr);
                String code = qlResponse.getString("code");

                if ("200".equals(code)) {
                    logger.info("200 响应 {}", qlResponse);
                    result = (JSONObject) qlResponse.get("data");
                    return true;
                } else if ("400".equals(code)) {
                    logger.info("400 响应 {}", qlResponse);
                    result = (JSONObject) qlResponse.get("message");
                    break;
                }
            }

            retryCount++;
            sleep(1000);
        }
        return false;

    }

    // http://134.175.126.60:45700/api/crons?searchValue=&page=1&size=20&filters={}&queryString={%22filters%22:null,%22sorts%22:null,%22filterRelation%22:%22and%22}&t=1703148561868

    /**
     * @param searchKey
     * @return
     * @throws
     * @description 获取定时任务列表
     */
    public List<Cron> getCron(String searchKey) {
        String token = getToken();
        List<Cron> cronList = new ArrayList<>();
        int maxRetryCount = 3;
        int retryCount = 0;

        String getUrl = GET_CRON + "?searchValue=&t=1630032278171";
        if (Util.isNotEmpty(searchKey)) {
            getUrl = GET_CRON + "?searchValue=" + searchKey + "&t=1630032278171";
        }
        while (cronList.size() == 0 && retryCount < maxRetryCount) {
            String responseStr = HttpRequest.get(getUrl).header("Authorization", "Bearer " + token).execute().body();
            if (ObjectUtil.isNotEmpty(responseStr)) {
                JSONObject qlResponse = JSONObject.parseObject(responseStr);
                String code = qlResponse.getString("code");
                //{"code":200,"data":{"data":[],"total":0}}
                if ("200".equals(code)) {
                    logger.info("200 响应 {}", qlResponse);
                    JSONObject dataObj = qlResponse.getJSONObject("data");
                    if (dataObj.getInteger("total") == 0) {


                    } else {

                        ArrayList data = JSONObject.parseObject(dataObj.getString("data"), ArrayList.class);
                        System.out.println(data.size());

                    }
                } else if ("400".equals(code)) {
                    logger.info("400 响应 {}", qlResponse);

                    //result = (JSONArray) qlResponse.get("message");
                }
                retryCount++;
                sleep(500);
            }
        }
        return null;
    }

    /*
     * 请求网址:
     * http://134.175.126.60:45700/api/crons/run?t=1703148561868
     * 请求方法:
     * PUT*/
    //public JSONObject runCron(String cronId) {
    //    String token = getToken();
    //    if (StrUtil.isNotEmpty(token)) {
    //        for (int i = 0; i < 3; i++) {
    //            String responseStr = HttpRequest.put(GET_CRON + "?cronId=" + cronId).header("Authorization", "Bearer " + token).execute().body();
    //            if (ObjectUtil.isNotEmpty(responseStr)) {
    //                QLResponse qlResponse = JSON.parseObject(responseStr, QLResponse.class);
    //                if (Objects.equals(String.valueOf(qlResponse.getCode()), "200")) {
    //                    return qlResponse.getData();
    //                }
    //            }
    //            sleep(500);
    //        }
    //    }
    //    return null;
    //}

    /**
     * }
     * async ["getLoginedUserInfo"](_0x4ef1fe = {}) {
     * let _0x26ac1b = false;
     * try {
     * const _0x3daa7c = {
     * "token": this.token
     * };
     * const _0xe8bb64 = {
     * "fn": "getLoginedUserInfo",
     * "method": "get",
     * "url": "https://i.meituan.com/wrapapi/getLoginedUserInfo",
     * "searchParams": _0x3daa7c
     * };
     * let {
     * result: _0x48e5d7
     * } = await this.request(_0xe8bb64);
     * if (_0x48e5d7?.["mobile"]) {
     * _0x26ac1b = true;
     * this.name = _0x48e5d7.nickName;
     * this.userId = Number(_0x48e5d7.userId);
     * this.log("登录成功");
     * } else {
     * this.log("获取账号信息失败, ck可能失效");//, {"notify": true}
     * await expireNotify(this.userId, this.index);
     * }
     * } catch (_0x232c57) {
     * console.log(_0x232c57);
     * } finally {
     * return _0x26ac1b;
     * }
     * }
     */

    // 通过token 获取用户信息
    // url https://i.meituan.com/wrapapi/getLoginedUserInfo
    //    参数 token
    //    get
    public HashMap<String, String> getLoginedUserInfo(String token) {
        String responseStr = HttpRequest.get("https://i.meituan.com/wrapapi/getLoginedUserInfo" + "?token=" + token).header("token", token).execute().body();
        HashMap<String, String> result = new HashMap<>();
        if (ObjectUtil.isNotEmpty(responseStr)) {
            JSONObject qlResponse = JSON.parseObject(responseStr);
            //{"userId":"3822095266","nickName":"XLP200660795","growthValue":null,"growthLevel":null,"avatarUrl":"","mobile":"15817969021"}
            if (qlResponse.containsKey("mobile")) {
                result.put("mobile", qlResponse.getString("mobile"));
            }
            if (qlResponse.containsKey("nickName")) {
                result.put("nickName", qlResponse.getString("nickName"));
            }
        }
        return result;
    }

    // new QLEnv(value, name, remarks)
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    private static class QLEnv {
        private String value;
        private String name;
        private String remarks;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    private class Cron {
        private long id;
        private String name;
        private String command;
        private String schedule;
        private String timestamp;
        private boolean saved;
        private long status;
        private long isSystem;
        private long pid;
        private long isDisabled;
        private long isPinned;
        private String logPath;
        private List<Object> labels;
        private long lastRunningTime;
        private long lastExecutionTime;
        private long subID;
        private String createdAt;
        private String updatedAt;
    }

}
