package com.dsk.system.utils;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dsk.acc.openapi.api.AccClient;
import com.dsk.acc.openapi.client.Config;
import com.dsk.acc.openapi.client.util.CommonUtils;
import com.dsk.common.constant.TenantConstants;
import com.dsk.common.core.page.TableDataInfo;
import com.dsk.common.tenant.helper.TenantHelper;
import com.dsk.system.domain.SysConfig;
import com.dsk.system.mapper.SysConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class DskOpenApiUtil {


    private static Config config;

    @Resource
    private SysConfigMapper sysConfigMapper;


    /**
     * <b>application/json请求</b>
     *
     * @param path    请求路径
     * @param bodyMap 参数体
     * @return
     */
    public Map<String, Object> requestBody(String path, Map<String, Object> bodyMap) {
        return request(path, bodyMap, "json");
    }

    public Map<String, Object> requestBodyLocal(String path, Map<String, Object> bodyMap) {
        String post = HttpUtil.post("http://127.0.0.1:8766" + path, JSONUtil.toJsonStr(bodyMap));
        return CommonUtils.assertAsMap(CommonUtils.parseJSON(post));
    }

    public Map<String, Object> requestBodyWithHeader(String path, Map<String, Object> bodyMap, Map<String, String> headerMap) {
        return requestWithHeader(path, bodyMap, "json", headerMap);
    }

    /**
     * <b>application/x-www-form-urlencoded请求</b>
     *
     * @param path    请求路径
     * @param bodyMap 参数体
     * @return
     */
    public Map<String, Object> requestForm(String path, Map<String, Object> bodyMap) {
        return request(path, bodyMap, "form");
    }

    /**
     * <b>开放平台统一请求</b>
     *
     * @param path        请求路径
     * @param bodyMap     参数体
     * @param reqBodyType 请求格式
     * @return
     */
    public Map<String, Object> request(String path, Map<String, Object> bodyMap, String reqBodyType) {
        try {
            if (ObjectUtils.isEmpty(config)) initApiConfig();
            AccClient.init(config);
            log.error(">>>>>>config:"+JSONUtil.toJsonStr(config));
            Map<String, ?> res = AccClient.request(reqBodyType, path, bodyMap);
            if (!res.containsKey("headers") || !res.containsKey("body")) {
                throw new RuntimeException(String.format("请求无返回:path=%s", path));
            }
            Object resBody = res.get("body");
            if (resBody == null) {
                return null;
            }
            return CommonUtils.assertAsMap(resBody);
        } catch (Exception e) {
            throw new RuntimeException(String.format("请求异常:path=%s,err=%s", path, e.getMessage()));
        }
    }

    /**
     * <b>开放平台统一请求</b>
     *
     * @param path        请求路径
     * @param bodyMap     参数体
     * @param reqBodyType 请求格式
     * @return
     */
    public Map<String, Object> requestWithHeader(String path, Map<String, Object> bodyMap, String reqBodyType, Map<String, String> headerMap) {
        try {
            if (ObjectUtils.isEmpty(config)) initApiConfig();
            AccClient.init(config);
            Map<String, ?> res = AccClient.request(reqBodyType, path, bodyMap, headerMap);
            if (!res.containsKey("headers") || !res.containsKey("body")) {
                throw new RuntimeException(String.format("请求无返回:path=%s", path));
            }
            Object resBody = res.get("body");
            if (resBody == null) {
                return null;
            }
            return CommonUtils.assertAsMap(resBody);
        } catch (Exception e) {
            throw new RuntimeException(String.format("请求异常:path=%s,err=%s", path, e.getMessage()));
        }
    }


    public TableDataInfo responsePage(Map<String, Object> resMap) throws Exception {
        Integer code = MapUtils.getInteger(resMap, "code", 300);
        Map data = MapUtils.getMap(resMap, "data", null);
        if (200 != code) throw new RuntimeException();
        Integer count = MapUtils.getInteger(data, "totalCount", 0);
        Object list = MapUtils.getObject(data, "list", "");
        return new TableDataInfo((List<?>) list, count);
    }

    /***
     *@Description: 特殊返回
     *@Param:
     *@return: com.dsk.common.core.page.TableDataInfo
     *@Author: Dgm
     *@date: 2023/12/15 15:04
     */
    public TableDataInfo responsePageT(Map<String, Object> resMap) throws Exception {
        Integer code = MapUtils.getInteger(resMap, "code", 300);
        Map data = MapUtils.getMap(resMap, "data", null);
        if (200 != code) {
            throw new RuntimeException();
        }
        Integer count = MapUtils.getInteger(data, "totalCount", 0);
        Object list = MapUtils.getObject(data, "list", "");
        Object object = MapUtils.getObject(data, "obj", "");
        return new TableDataInfo((List<?>) list, count, object);
    }

    private void initApiConfig() {
        TenantHelper.ignore(() -> {
            SysConfig accessKeyId = sysConfigMapper.selectOne(Wrappers.<SysConfig>lambdaQuery().eq(SysConfig::getTenantId, TenantConstants.DEFAULT_TENANT_ID).eq(SysConfig::getConfigKey, "dsk-Appkey"));
            SysConfig accessKeySecret = sysConfigMapper.selectOne(Wrappers.<SysConfig>lambdaQuery().eq(SysConfig::getTenantId, TenantConstants.DEFAULT_TENANT_ID).eq(SysConfig::getConfigKey, "dsk-AppSecret"));
            SysConfig endPoint = sysConfigMapper.selectOne(Wrappers.<SysConfig>lambdaQuery().eq(SysConfig::getTenantId, TenantConstants.DEFAULT_TENANT_ID).eq(SysConfig::getConfigKey, "dsk-Domain"));
            log.error(">>>>>>config:"+JSONUtil.toJsonStr(config));
            config = new Config(accessKeyId.getConfigValue(), accessKeySecret.getConfigValue())
                    .setEndpoint(endPoint.getConfigValue());
        });
    }

}
