package com.njzscloud.dispose.wechat.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.security.contant.AuthWay;
import com.njzscloud.common.security.support.UserDetail;
import com.njzscloud.common.security.util.SecurityUtil;
import com.njzscloud.dispose.sys.auth.service.AuthService;
import com.njzscloud.dispose.sys.role.pojo.result.RoleDetailResult;
import com.njzscloud.dispose.sys.user.pojo.entity.UserAccountEntity;
import com.njzscloud.dispose.sys.user.service.UserAccountService;
import com.njzscloud.dispose.sys.user.service.UserRoleService;
import com.njzscloud.dispose.wechat.pojo.param.WechatParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static com.njzscloud.common.security.contant.Constants.ROLE_ANONYMOUS;
import static com.njzscloud.common.security.contant.Constants.ROLE_AUTHENTICATED;

/**
 * 资金流水
 *
 * @author ljw
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WechatService {

    private final UserAccountService userAccountService;
    private final AuthService authService;
    private final UserRoleService userRoleService;

    /**
     * 获取openId
     *
     * @param param 获取openId入参
     */
    public Map<String, Object> getOpenId(WechatParam param) {
        log.info("登录参数 - code: {}, encryptedData长度: {}, iv: {}",
            param.getCode(),
            param.getEncryptedData() != null ? param.getEncryptedData().length() : 0,
            param.getIv());

        String code = param.getCode();
        if (StrUtil.isBlank(code)) {
            throw Exceptions.clierr("授权码code不能为空");
        }

        String appid = "wx3c06d9dd4e56c58d";
        String secret = "ff280a71a4c06fc2956178f8c472ef96";

        // 使用code向微信服务器换取session_key和openid
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code="
            + param.getCode() + "&grant_type=authorization_code";

        // 使用 Hutool 发送 GET 请求
        log.info("开始请求微信接口: {}", url);
        long startTime = System.currentTimeMillis();
        String response;
        try {
            HttpResponse httpResponse = HttpRequest.get(url)
                    .timeout(30000)
                    .execute();
            response = httpResponse.body();
            long connectTime = System.currentTimeMillis() - startTime;
            log.info("微信接口连接耗时: {}ms", connectTime);
            httpResponse.close();
        } catch (Exception e) {
            log.error("调用微信获取openId接口网络异常: ", e);
            throw Exceptions.clierr("网络请求失败");
        }
        long totalTime = System.currentTimeMillis() - startTime;
        log.info("微信接口总耗时: {}ms", totalTime);
        JSONObject jsonObject = JSONObject.parseObject(response);
        if (null == jsonObject) {
            throw Exceptions.clierr("获取小程序信息失败");
        }
        // 检查微信服务器返回的错误码
        if (jsonObject.containsKey("errcode")) {
            throw Exceptions.clierr("获取小程序信息失败，错误码：" + jsonObject.getInteger("errcode")
                + "，错误信息：" + jsonObject.getString("errmsg"));
        }
        String openid = jsonObject.getString("openid");
        String sessionKey = jsonObject.getString("session_key");
        log.info("获取到openid: {}, sessionKey长度: {}", openid, sessionKey.length());
        Map<String, Object> map = new HashMap<>();
        UserAccountEntity entity = userAccountService.getOne(Wrappers.<UserAccountEntity>lambdaQuery().eq(UserAccountEntity::getWechatOpenid, openid));
        if (entity == null) {
            map.put("type", "register");
            map.put("openid", openid);
        } else {
            map.put("type", "login");
            List<RoleDetailResult> roleDetailResults = userRoleService.listRole(entity.getUserId());
            Set<String> roles = roleDetailResults.stream().map(RoleDetailResult::getRoleCode).collect(Collectors.toSet());
            roles.add(ROLE_AUTHENTICATED);
            roles.add(ROLE_ANONYMOUS);
            UserDetail userDetail = authService.my(entity.getUserId(), entity.getClientCode())
                .setAuthWay(AuthWay.WECHAT_MINI)
                .setRoles(roles);
            UserDetail detail = SecurityUtil.registrationUser(userDetail);
            map.put("userDetail", detail);
        }
        return map;
    }

    /**
     * 小程序手机号授权
     */
    public Map<String, Object> getMiniPhone(WechatParam param) {
        // 1. 从前端请求体中获取code
        String code = param.getCode();
        if (StrUtil.isBlank(code)) {
            throw Exceptions.clierr("授权码code不能为空");
        }

        // 2. 获取access_token
        String accessToken;
        try {
            accessToken = this.getAccessToken();
        } catch (Exception e) {
            log.error("获取access_token失败: ", e);
            throw Exceptions.clierr("服务暂不可用，请稍后重试");
        }
        // 3. 构建请求URL和参数
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;

        // 4. 使用 Hutool 发送 POST 请求（解决 412 错误）
        String requestBody = String.format("{\"code\":\"%s\"}", code);
        log.info("发送请求到微信接口，请求体: {}", requestBody);
        log.info("开始请求手机号授权接口: {}", url);

        String response;
        long startTime = System.currentTimeMillis();
        try {
            HttpResponse httpResponse = HttpRequest.post(url)
                    .body(requestBody)
                    .timeout(30000)
                    .execute();
            response = httpResponse.body();
            long connectTime = System.currentTimeMillis() - startTime;
            log.info("手机号授权接口连接耗时: {}ms", connectTime);
            httpResponse.close();
        } catch (Exception e) {
            log.error("调用微信授权手机号接口网络异常: ", e);
            throw Exceptions.clierr("网络请求失败");
        }
        long totalTime = System.currentTimeMillis() - startTime;
        log.info("手机号授权接口总耗时: {}ms", totalTime);
        JSONObject jsonObject = JSONObject.parseObject(response);
        log.info("微信接口返回原始数据: {}", response);

        // 5. 处理微信接口响应
        if (jsonObject == null) {
            throw Exceptions.clierr("获取手机信息失败，响应为空");
        }
        Integer errCode = jsonObject.getInteger("errcode");
        if (errCode != null && errCode != 0) {
            String errMsg = jsonObject.getString("errmsg");
            log.error("微信接口返回错误，errCode: {}, errMsg: {}", errCode, errMsg);
            throw Exceptions.clierr("授权失败: " + errMsg);
        }

        // 6. 解析并返回结构化的手机号信息
        JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
        if (phoneInfo == null) {
            throw Exceptions.clierr("响应中缺少手机号信息");
        }

        // 提取核心信息
        Map<String, Object> result = new HashMap<>();
        String phone = phoneInfo.getString("phoneNumber");
        result.put("phoneNumber", phone);
        result.put("purePhoneNumber", phoneInfo.getString("purePhoneNumber"));
        result.put("countryCode", phoneInfo.getString("countryCode"));

        // 记录日志（注意在生产环境需脱敏）
        log.info("手机号授权成功，国家码: {}，手机号: {}",
            phoneInfo.getString("countryCode"),
            phoneInfo.getString("purePhoneNumber"));
        return result;
    }

    /**
     * 获取全局唯一的Access Token（注意缓存，避免频繁调用）
     */
    private String getAccessToken() {
        String appid = "wx3c06d9dd4e56c58d";
        String secret = "ff280a71a4c06fc2956178f8c472ef96";
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;

        // 使用 Hutool 发送 GET 请求
        log.info("开始请求accessToken接口: {}", tokenUrl);
        long startTime = System.currentTimeMillis();
        String response;
        try {
            HttpResponse httpResponse = HttpRequest.get(tokenUrl)
                    .timeout(30000)
                    .execute();
            response = httpResponse.body();
            long connectTime = System.currentTimeMillis() - startTime;
            log.info("accessToken接口连接耗时: {}ms", connectTime);
            httpResponse.close();
        } catch (Exception e) {
            log.error("调用微信获取accessToken接口网络异常: ", e);
            throw Exceptions.clierr("网络请求失败");
        }
        long totalTime = System.currentTimeMillis() - startTime;
        log.info("accessToken接口总耗时: {}ms", totalTime);

        JSONObject jsonResponse = JSONObject.parseObject(response);

        if (jsonResponse == null || jsonResponse.containsKey("errcode")) {
            // 正确判断错误：当存在errcode，或响应为空时，才是失败
            String errMsg = jsonResponse != null ? jsonResponse.getString("errmsg") : "响应为空";
            log.error("获取Access Token失败: {}", errMsg);
            throw Exceptions.clierr("获取服务凭证失败");
        }
        String token = jsonResponse.getString("access_token");
        log.info("成功获取Access Token，有效期: {}秒", jsonResponse.getIntValue("expires_in"));
        return token;
    }

}
