package com.ruoyi.ai.service.impl;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.ai.domain.*;
import com.ruoyi.ai.service.*;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.AiUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.http.OkHttpUtils;
import com.ruoyi.common.utils.sign.Md5Utils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

@Service
@Slf4j
public class JinShaService implements IJinShaService {

    private final ObjectMapper objectMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);

    @Value("${jinsha.url}")
    private String url;
    @Value("${jinsha.appId}")
    private String appId;
    @Value("${jinsha.secret}")
    private String secret;
    @Value("${jinsha.notifyUrl}")
    private String notifyUrl;
    @Value("${jinsha.returnUrl}")
    private String returnUrl;

    @Autowired
    private IAiRechargeService aiRechargeService;
    @Autowired
    private IAiUserService aiUserService;
    @Autowired
    private IAiRechargeGiftGearService aiRechargeGiftGearService;
    @Autowired
    private IAiRechargeGiftService aiRechargeGiftService;
    @Autowired
    private IExchangeRateService exchangeRateService;

    @Override
    public PayResVO jinShaPay(Long gearId) throws Exception {

        //充值挡位查询
        AiRechargeGiftGear aiRechargeGiftGear = aiRechargeGiftGearService.selectAiRechargeGiftGearById(gearId);
        if (aiRechargeGiftGear == null) {
            throw new ServiceException("The gear position does not exist.", -1);
        }
        BigDecimal amount = aiRechargeGiftGear.getRechargeAmount();
        // 使用汇率服务转换金额（从CNY转换为目标货币，默认INR）
        amount = exchangeRateService.convertAmount(amount, "USD", "INR");

        // 生成订单号
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);
        String dateTime = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String orderNo = dateTime + "js" + uuid;

        // 金额转换为number类型（保留两位小数）
        String amountStr = String.format("%.2f", amount.doubleValue());

        // 构建回调地址和返回地址
        String notifyUrlFull = notifyUrl + "/api/pay/jinsha-callBack";
        String returnUrlFull = returnUrl + "/recharge";

        // 1. 配置签名参数（按照key排序：appid, amount, orderno, notify_url, return_url，不包含sign）
        TreeMap<String, Object> signParams = new TreeMap<>();
        signParams.put("appid", appId);
        signParams.put("amount", amountStr);
        signParams.put("orderno", orderNo);
        signParams.put("notify_url", notifyUrlFull);
        signParams.put("return_url", returnUrlFull);

        // 2. 生成签名
        String sign = this.generateSign(signParams);

        // 3. 构建请求参数（使用FormBody.Builder自动处理URL编码）
        FormBody.Builder formBuilder = new FormBody.Builder();
        formBuilder.add("appid", appId);
        formBuilder.add("amount", amountStr);
        formBuilder.add("orderno", orderNo);
        formBuilder.add("notify_url", notifyUrlFull);
        formBuilder.add("return_url", returnUrlFull);
        formBuilder.add("sign", sign);
        RequestBody requestBody = formBuilder.build();
        
        // 4. 构建 POST 请求
        Request request = new Request.Builder()
                .url(url + "/api/pay")
                .header("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
                .post(requestBody)
                .build();
        
        // 5. 发送请求并获取响应
        Response response = OkHttpUtils.newCall(request).execute();
        ResponseBody body = response.body();
        if (null == body) {
            log.error("jinsha支付请求的响应异常");
            throw new Exception("jinshapay responsebody is null");
        }
        String responseBody = body.string();
        log.info("jinsha支付请求响应: {}", responseBody);
        JinShaBodyRes jinShaBodyRes = objectMapper.readValue(responseBody, JinShaBodyRes.class);
        
        // 检查响应code，0表示成功，其他值表示失败
        Integer code = jinShaBodyRes.getCode();
        if (code == null || code != 0) {
            String msg = jinShaBodyRes.getMsg();
            log.error("jinsha支付请求失败，code: {}, msg: {}", code, msg);
            throw new ServiceException(msg != null ? msg : "支付请求失败", code != null ? code : -1);
        }
        
        // 检查返回的payurl
        String payUrl = null;
        if (jinShaBodyRes.getData() != null) {
            payUrl = jinShaBodyRes.getData().getPayurl();
        }
        if (payUrl == null || payUrl.trim().isEmpty()) {
            log.error("jinsha支付返回的payurl为空，订单号: {}", orderNo);
            throw new ServiceException("支付返回的支付链接为空", -1);
        }
        
        // 创建充值管理
        AiUser userInfo = aiUserService.getUserInfo(SecurityUtils.getAiUserId());
        AiRecharge aiRecharge = new AiRecharge();
        aiRecharge.setOrderNum(orderNo);
        aiRecharge.setUserId(SecurityUtils.getAiUserId());
        aiRecharge.setAmount(amount);
        aiRecharge.setGearId(gearId);
        aiRecharge.setGearAmount(aiRechargeGiftGear.getRechargeAmount());
        aiRecharge.setSource(userInfo.getSource());
        AiRechargeGift aiRechargeGift = aiRechargeGiftService.selectAiRechargeGiftById(aiRechargeGiftGear.getRechargeId());
        aiRecharge.setPayType(aiRechargeGift.getPayType());
        aiRecharge.setPayUrl(payUrl);
        aiRechargeService.insertAiRecharge(aiRecharge);
        
        PayResVO payResVO = new PayResVO();
        payResVO.setOrderNo(orderNo);
        payResVO.setPayUrl(payUrl);
        return payResVO;
    }

    @Override
    @Transactional
    public AjaxResult jinShaCall(JinShaBodyCall req) {
        log.info("jinsha支付回调，订单号: {}, 状态: {}", req.getOrderno(), req.getStatus());
        
        // 验证签名
        TreeMap<String, Object> params = new TreeMap<>();
        params.put("status", req.getStatus());
        params.put("orderno", req.getOrderno());
        params.put("appid", req.getAppid());
        params.put("amount", req.getAmount());
        StringBuilder append = this.append(params);
        String sign = this.sign(append);
        if (!sign.equals(req.getSign())) {
            log.error("jinsha支付回调签名错误，订单号: {}, 期望签名: {}, 实际签名: {}", 
                    req.getOrderno(), sign, req.getSign());
            return AjaxResult.error("签名验证失败");
        }
        
        // 处理订单状态
        // status:0=>处理中, status:1=>成功, status:2=>失败
        Integer status = req.getStatus();
        if (status == null) {
            log.error("jinsha支付回调状态为空，订单号: {}", req.getOrderno());
            return AjaxResult.error("状态为空");
        }
        
        if (status == 1) {
            // 充值成功处理
            log.info("jinsha支付成功，订单号: {}", req.getOrderno());
            aiRechargeService.addRecharge(req.getOrderno());
            return AjaxResult.success();
        } else if (status == 2) {
            // 支付失败
            log.warn("jinsha支付失败，订单号: {}", req.getOrderno());
            // 这里可以添加失败处理逻辑，比如更新订单状态为失败
            return AjaxResult.success();
        } else {
            // 处理中（status:0）
            log.info("jinsha支付处理中，订单号: {}", req.getOrderno());
            return AjaxResult.success();
        }
    }

    /**
     * 生成签名
     * 按照文档要求：key=value&key=value&...&secret=secret，然后MD5
     */
    private String generateSign(TreeMap<String, Object> sortedParams) {
        StringBuilder paramSb = new StringBuilder();
        for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            // 拼接格式：key=value&
            paramSb.append(key).append("=").append(value).append("&");
        }
        // 最后添加secret
        paramSb.append("secret=").append(secret);
        String signSource = paramSb.toString();
        log.debug("jinsha签名源字符串: {}", signSource);
        return Md5Utils.hash(signSource);
    }

    /**
     * 旧的签名方法（回调使用）
     */
    private StringBuilder append(TreeMap<String, Object> sortedParams) {
        StringBuilder paramSb = new StringBuilder();
        for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            // 拼接格式：key=value&（末尾的&会被后续secret覆盖）
            paramSb.append(key).append("=").append(value).append("&");
        }
        return paramSb;
    }

    private String sign(StringBuilder paramSb) {
        String signSource = paramSb.append("secret=").append(secret).toString();
        return Md5Utils.hash(signSource);
    }


}
