package cn.newfeifan.mall.module.pay.controller.app.fuyouorder.vo;

import lombok.Data;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.module.pay.enums.ErrorCodeConstants.SIGN_MD5_ERROR;

@Data
public class FuYouPaymentRequestVO {

    /**
     * 版本号
     */
    private String version;

    /**
     * 商户号，富友分配的商户号
     */
    private String mchntCd;

    /**
     * 随机字符串
     */
    private String randomStr;

    /**
     * 订单总金额，以分为单位
     */
    private Double orderAmt;

    /**
     * 商户订单号
     */
    private String mchntOrderNo;

    /**
     * 商品标识
     */
    private String productId;

    /**
     * 交易开始时间，格式: yyyyMMddHHmmss
     */
    private LocalDateTime txnBeginTs;

    /**
     * 商品描述
     */
    private String goodsDes;

    /**
     * 商品详情
     */
    private String goodsDetail;

    /**
     * 商品标记
     */
    private String goodsTag;

    /**
     * 终端标识，如设备8字节数字字母组合
     */
    private String termId;

    /**
     * 终端IP
     */
    private String termIp;

    /**
     * 附加信息
     */
    private String addnInf;

    /**
     * 货币类型，默认人民币: CNY
     */
    private String currType;

    /**
     * 接收富友异步通知回调地址
     */
    private String notifyUrl;

    /**
     * 支付限制，如不能使用信用卡
     */
    private String limitPay;

    /**
     * 交易类型
     */
    private String tradeType;

    /**
     * 用户标识，支付宝服务窗为user_id，微信公众号为用户的openid
     */
    private String openid;

    /**
     * 子商户用户标识
     */
    private String subOpenid;

    /**
     * 子商户公众号或商户的appid
     */
    private String subAppid;

    /**
     * 富友终端号，如果不是富友的POS终端，此字段不要填，否则会影响清算
     */
    private String reservedFyTermId;

    /**
     * 交易关闭时间，单位分钟，例如：60（1小时），默认填0（2小时）
     */
    private Integer reservedExpireMinute;

    /**
     * 用户身份证号码，实名保险类交易必填
     */
    private String reservedUserCreid;

    /**
     * 用户姓名
     */
    private String reservedUserTruename;

    /**
     * 用户手机号
     * */
    private String reservedUserMobile;

    /**
     * 保险公司订单号，认证机构单号（使用英文逗号分隔）
     */
    private String reservedBxnoInf;

    /**
     * 富友终端类型
     * 0: 其他
     * 1: 富友终端
     * 2: POS机
     * 3: 台卡
     * 4: PC软件
     */
    private Integer reservedFyTermType;

    /**
     * 终端序列号
     */
    private String reservedFyTermSn;

//    /**
//     * 设备信息，透传给微信，用于单品券核销
//     */
//    private String reservedDeviceInfo;

//    /**
//     * 花呗分期相关信息的JSON串
//     */
//    private String reservedAliExtendParams;
//
//    /**
//     * 花呗分期期数：仅支持3、6期
//     */
//    private Integer lhbFqNum;
//
//    /**
//     * 花呗分期商家手续费比例，目前仅支持用户出资，如需使用，请填写0
//     */
//    private Double lhbFqSellerPercent;
//
//    /**
//     * 行业数据回流信息
//     */
//    private String lindustryRefluxInfo;
//
//    /**
//     * 点餐场景类型
//     * qr_order: 店内扫码点餐
//     * pre_order: 预点到店自提
//     * home_delivery: 外送到家
//     */
//    private String lfoodOrderType;


    /**
     * 商户密钥，系统分配
     */
    private String mchntKey;

    /**
     * 签名
     */
    private String sign;

    /**
     * 生成签名
     *
     * @return 签名字符串
     */
    public String getSign() {
        // 拼接签名字符串，字段间用 "|" 分隔
        StringBuilder signContent = new StringBuilder();
        signContent.append(this.orderAmt)
                .append("|")
                .append(this.mchntOrderNo)
                .append("|")
                .append(this.txnBeginTs)
                .append("|")
                .append(this.goodsDes)
                .append("|")
                .append(this.termId)
                .append("|")
                .append(this.termIp)
                .append("|")
                .append(this.mchntCd)
                .append("|")
                .append(this.notifyUrl)
                .append("!")
                .append(this.tradeType)
                .append("(")
                .append(this.randomStr)
                .append(")")
                .append(this.version)
                .append("|")
                .append(this.mchntKey);

        // 使用 MD5 算法加密签名字符串
        return encryptMd5(signContent.toString());
    }

    /**
     * 使用MD5算法加密给定字符串。注意：MD5算法在安全性要求高的场景中不再安全，应考虑使用更安全的算法。
     *
     * @param content 需要加密的字符串
     * @return 加密后的字符串
     */
    private String encryptMd5(String content) {
        try {
            // 指定使用UTF-8字符编码，避免不同环境下的不一致问题
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(content.getBytes(StandardCharsets.UTF_8));
            BigInteger no = new BigInteger(1, messageDigest);

            // 使用String.format简化了补0的逻辑，提高代码的可读性和简洁性

            return String.format("%032x", no);
        } catch (NoSuchAlgorithmException e) {
            throw exception(SIGN_MD5_ERROR);
        }
    }
}