package com.ruoyi.cms.util.oauth;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.entity.tymh.nwToken.NwTokenResult;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

/**
 * OAuth2.0 认证工具类（合并相似方法）
 */
@Component
public class OauthClient {

    /*====================== 内网 ======================*/
    // 网关请求-内网获取token
    @Value("${oauth.usptnw.nwGatewayGetTokenUrl}")
    private String nwGatewayGetTokenUrl;
    // 网关请求-内网获取用户信息
    @Value("${oauth.usptnw.nwGatewayGetUserInfoUrl}")
    private String nwGatewayGetUserInfoUrl;

    /*====================== 外网 ======================*/
    //post-外网注册地址
    @Value("${oauth.usptww.wwRegisterPostUrl}")
    private String wwRegisterPostUrl;
    // post-外网获取token
    @Value("${oauth.usptww.wwTokenPostUrl}")
    private String wwTokenPostUrl;
    //post-外网获取用户信息
    @Value("${oauth.usptww.wwQueryWebPersonalInfoPostUrl}")
    private String wwQueryWebPersonalInfoPostUrl;
    //post-外网获取单位信息
    @Value("${oauth.usptww.wwQueryWebEnterpriseInfoPostUrl}")
    private String wwQueryWebEnterpriseInfoPostUrl;

    /*====================== 统一门户 ======================*/
    //用户新增接口
    @Value("${oauth.tyAddUserUrl}")
    private String tyAddUserUrl;
    //获取当前用户有权系统列表
    @Value("${oauth.tyQueryUserSysListUrl}")
    private String tyQueryUserSysListUrl;
    //获取当前用户有权角色列表
    @Value("${oauth.tyQueryUserRoleListUrl}")
    private String tyQueryUserRoleListUrl;
    //获取角色功能权限信息
    @Value("${oauth.tyQueryRoleInfoUrl}")
    private String tyQueryRoleInfoUrl;
    //获取用户详细信息
    @Value("${oauth.tyQueryUserInfo}")
    private String tyQueryUserInfo;
    //获取机构详细信息
    @Value("${oauth.tyQueryUnitInfo}")
    private String tyQueryUnitInfo;
    //客户端id
    @Value("${oauth.appid}")
    private String appid;
    //授权码
    @Value("${oauth.clientsecretkey}")
    private String clientsecretkey;
    // 超时配置
    @Value("${oauth.connect-timeout:10}")
    private int connectTimeout;
    @Value("${oauth.read-timeout:30}")
    private int readTimeout;
    @Value("${oauth.write-timeout:30}")
    private int writeTimeout;

    private static final String GATEWAY_AUTH_HEADER = "X-Gateway-Token"; // 网关鉴权头字段

    /**
     * 获取内网token
     * @return
     */
    public String nwGetToken(String code) throws IOException, TimeoutException, OAuthException{
        NwTokenResult nwTokenResult=null;
        if (StringUtils.isEmpty(code)) {
            throw new IllegalArgumentException("授权码code不能为空");
        }

        Map<String, Object> params = new HashMap<>(2);
        params.put("appid", appid);
        params.put("code", code);

        // 3. 组装请求头（含网关鉴权）
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json;charset=UTF-8");
        if (StringUtils.isNotEmpty(nwGatewayGetTokenUrl)) {
            headers.put(GATEWAY_AUTH_HEADER, nwGatewayGetTokenUrl);
        }

        // 4. 网关调用接口（POST JSON）
        HttpUtils.HttpResult result = HttpUtils.doPostJson(
                nwGatewayGetTokenUrl,
                JSON.toJSONString(params),
                headers,
                connectTimeout,
                readTimeout,
                writeTimeout
        );

        // 5. 响应解析（直接映射到NwTokenResult）
        if (!result.isSuccess()) {
            throw new OAuthTokenException(
                    String.format("获取访问令牌失败，网关响应状态码：%d", result.getStatusCode()),
                    result.getStatusCode(),
                    result.getResponseBody()
            );
        }

        try {
            nwTokenResult = JSON.parseObject(result.getResponseBody(), NwTokenResult.class);
            if (nwTokenResult == null) {
                throw new OAuthParseException("响应体解析失败，返回空对象", null);
            }

            if ("1".equals(nwTokenResult.getErrflag())) {
                throw new OAuthTokenException(
                        String.format("授权认证服务返回错误：%s", nwTokenResult.getErrtext()),
                        result.getStatusCode(),
                        result.getResponseBody()
                );
            }

            if (StringUtils.isEmpty(nwTokenResult.getAccessToken())) {
                throw new OAuthParseException("响应缺少核心字段：Access-Token", null);
            }
        } catch (JSONException e) {
            throw new OAuthParseException("访问令牌响应解析失败", e);
        }
        return nwTokenResult.getAccessToken();
    }

    public static class TokenInfo {
        private final String accessToken; // 访问令牌
        private final Long expiresIn;     // 过期时间（秒）

        public TokenInfo(String accessToken, Long expiresIn) {
            this.accessToken = accessToken;
            this.expiresIn = expiresIn;
        }

        // getter
        public String getAccessToken() { return accessToken; }
        public Long getExpiresIn() { return expiresIn; }
    }

    // ====================== 异常类（保持不变） ======================
    public static class OAuthException extends Exception {
        private final int statusCode;
        private final String responseBody;

        public OAuthException(String message, int statusCode, String responseBody) {
            super(message);
            this.statusCode = statusCode;
            this.responseBody = responseBody;
        }

        public OAuthException(String message, Throwable cause) {
            super(message, cause);
            this.statusCode = -1;
            this.responseBody = null;
        }

        public int getStatusCode() { return statusCode; }
        public String getResponseBody() { return responseBody; }
    }

    public static class OAuthTokenException extends OAuthException {
        public OAuthTokenException(String message, int statusCode, String responseBody) {
            super(message, statusCode, responseBody);
        }
    }

    public static class OAuthUserInfoException extends OAuthException {
        public OAuthUserInfoException(String message, int statusCode, String responseBody) {
            super(message, statusCode, responseBody);
        }
    }

    public static class OAuthParseException extends OAuthException {
        public OAuthParseException(String message, Throwable cause) {
            super(message, cause);
        }
    }

}