package com.seeyon.apps.esign.service;

import com.seeyon.aicloud.common.JsonUtils;
import com.seeyon.apps.esign.config.EsignConfigProvider;
import com.seeyon.apps.esign.constants.EsignApiUrl;
import com.seeyon.apps.esign.constants.EsignConfigConstants;
import com.seeyon.apps.esign.po.esignapi.EsignApiHeader;
import com.seeyon.apps.esign.po.esignapi.EsignBaseResp;
import com.seeyon.apps.esign.po.esignapi.EsignToken;
import com.seeyon.apps.esign.utils.HttpClient;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


public class TokenCacheManager {

    private EsignConfigProvider configProvider = EsignConfigProvider.getInstance();
    private final ConcurrentHashMap<String, EsignToken> tokenRef = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    private static final long CHECK_INTERVAL = 2 * 60 * 60 * 1000; // 120分钟检查一次

    private boolean checkExpired(String token,String appId) {
        EsignApiHeader esignApiHeader = EsignApiHeader.build();
        try {
            esignApiHeader.token(token).appId(appId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //获取orgId
        String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + getOrgNameByAppId(appId);
        String reqUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr;
        String orgInfoRespStr = HttpClient.httpGet(reqUrl, esignApiHeader.convert2Headers(), "UTF-8");
        EsignBaseResp orgInfoResp = JsonUtils.parseObject(orgInfoRespStr, EsignBaseResp.class);
        if(orgInfoResp.getCode() == 401) {
            return true;
        }
        return false;
    }

    public String getOrgIdByOrgName(String orgName) {
        EsignApiHeader esignApiHeader = EsignApiHeader.build();
        String appId = getAppIdByOrgName(orgName);
        try {
            esignApiHeader.token(getToken(appId)).appId(appId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //获取orgId
        String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + orgName;
        String reqUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr;
        String orgInfoRespStr = HttpClient.httpGet(reqUrl, esignApiHeader.convert2Headers(), "UTF-8");
        EsignBaseResp orgInfoResp = JsonUtils.parseObject(orgInfoRespStr, EsignBaseResp.class);
        Map<String, Object> orgData = (Map<String, Object>) orgInfoResp.getData();
        return  (String) orgData.get("orgId");
    }

    public String getOrgIdByOrgName(String orgName,String appId) {
        EsignApiHeader esignApiHeader = EsignApiHeader.build();
        try {
            esignApiHeader.token(getToken(appId)).appId(appId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //获取orgId
        String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + orgName;
        String reqUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr;
        String orgInfoRespStr = HttpClient.httpGet(reqUrl, esignApiHeader.convert2Headers(), "UTF-8");
        EsignBaseResp orgInfoResp = JsonUtils.parseObject(orgInfoRespStr, EsignBaseResp.class);
        Map<String, Object> orgData = (Map<String, Object>) orgInfoResp.getData();
        return  (String) orgData.get("orgId");
    }

    public String getToken(String appId) {
        EsignToken current = tokenRef.get(appId);
        if (current != null && !checkExpired(current.getTokenStr(),appId)) {
            return current.getTokenStr();
        }
        return refreshToken(appId);
    }

    private String refreshToken(String appId) {
        EsignToken newToken = fetchNewToken(appId);
        tokenRef.put(appId,newToken);
        return newToken.getTokenStr();
    }

    private void checkTokenExpiry(String appId) {
        EsignToken current = tokenRef.get(appId);
        if (current != null && isTokenExpired(current)) {
            refreshToken(appId);
        }
    }

    private boolean isTokenExpired(EsignToken token) {
        return System.currentTimeMillis() >= token.getTtl();
    }

    private EsignToken fetchNewToken(String appId) {
        // 实际获取token的逻辑
        String queryStr = "?appId=" + appId + "&secret=" + getSecretByAppId(appId) + "&grantType=client_credentials";
        String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.TOKEN_GET_URL + queryStr;
        String respStr = HttpClient.httpGet(url, null, null);
        EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class);
        if(esignBaseResp.getCode() != 0) {
            throw new RuntimeException("获取e签宝token失败");
        }
        Map<String,Object> dataMap = (Map<String, Object>) esignBaseResp.getData();
        String token = (String) dataMap.get("token");
        Long ttl = Long.parseLong((String) dataMap.get("expiresIn")) ;
        String refreshToken = (String) dataMap.get("refreshToken");
        EsignToken esignToken = new EsignToken();
        esignToken.setTokenStr(token);
        esignToken.setTtl(ttl);
        esignToken.setRefreshToken(refreshToken);
        return esignToken;
    }

    public void shutdown() {
        scheduler.shutdown();
    }

    public String getOrgNameByAppId(String appId) {
        String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_UNITMAP);
        Map<String,String> map = JsonUtils.parseObject(configMap, Map.class);
        return map.get(appId);
    }

    public String getSecretByAppId(String appId) {
        String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_SECRETMAP);
        Map<String,String> map = JsonUtils.parseObject(configMap, Map.class);
        return map.get(appId);
    }

    public String getAppIdByOrgName(String orgName) {
        String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_UNITMAP);
        Map<String,String> map = JsonUtils.parseObject(configMap, Map.class);
        for (String key : map.keySet()) {
            if(map.get(key).equals(orgName)) {
                return key;
            }
        }
        return null;
    }

    public List<String> getAppIds() {
        String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_SECRETMAP);
        Map<String,String> map = JsonUtils.parseObject(configMap, Map.class);
        return map.keySet().stream().collect(Collectors.toList());
    }
}