package com.gxwebsoft.payment.strategy;

import cn.hutool.core.util.IdUtil;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.payment.constants.PaymentConstants;
import com.gxwebsoft.payment.dto.PaymentRequest;
import com.gxwebsoft.payment.dto.PaymentResponse;
import com.gxwebsoft.payment.enums.PaymentStatus;
import com.gxwebsoft.payment.enums.PaymentType;
import com.gxwebsoft.payment.exception.PaymentException;
import com.gxwebsoft.payment.service.WxPayConfigService;
import com.gxwebsoft.payment.service.WxPayNotifyService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;

/**
 * 微信Native支付策略实现
 * 处理微信Native扫码支付
 *
 * @author 科技小王子
 * @since 2025-01-26
 */
@Slf4j
@Component
public class WechatNativeStrategy implements PaymentStrategy {

    @Resource
    private WxPayConfigService wxPayConfigService;

    @Resource
    private WxPayNotifyService wxPayNotifyService;

    @Override
    public PaymentType getSupportedPaymentType() {
        return PaymentType.WECHAT_NATIVE;
    }

    @Override
    public void validateRequest(PaymentRequest request) throws PaymentException {
        if (request == null) {
            throw PaymentException.paramError("支付请求不能为空");
        }

        if (request.getTenantId() == null) {
            throw PaymentException.paramError("租户ID不能为空");
        }

        if (request.getUserId() == null) {
            throw PaymentException.paramError("用户ID不能为空");
        }

        if (request.getAmount() == null || request.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw PaymentException.amountError("支付金额必须大于0");
        }

        if (!StringUtils.hasText(request.getSubject())) {
            throw PaymentException.paramError("订单标题不能为空");
        }

        // 验证金额范围
        if (request.getAmount().compareTo(new BigDecimal("0.01")) < 0) {
            throw PaymentException.amountError("支付金额不能小于0.01元");
        }

        if (request.getAmount().compareTo(new BigDecimal("999999.99")) > 0) {
            throw PaymentException.amountError("支付金额不能超过999999.99元");
        }

        // 验证订单标题长度
        if (request.getSubject().length() > PaymentConstants.Config.DESCRIPTION_MAX_LENGTH) {
            throw PaymentException.paramError("订单标题长度不能超过" + PaymentConstants.Config.DESCRIPTION_MAX_LENGTH + "个字符");
        }

        log.debug("微信Native支付请求参数验证通过, 租户ID: {}, 金额: {}",
            request.getTenantId(), request.getFormattedAmount());
    }

    @Override
    public PaymentResponse createPayment(PaymentRequest request) throws PaymentException {
        log.info("{}, 支付类型: {}, 租户ID: {}, 金额: {}",
            PaymentConstants.LogMessage.PAYMENT_START, getSupportedPaymentType(),
            request.getTenantId(), request.getFormattedAmount());

        try {
            // 验证请求参数
            validateRequest(request);

            // 生成订单号
            String orderNo = generateOrderNo(request);
            log.info("生成的订单号: {}", orderNo);

            // 获取Native支付的Payment配置（包含appId等信息）
            Payment paymentConfig = wxPayConfigService.getPaymentConfigForStrategy(request.getTenantId());

            // 获取微信支付配置
            Config wxPayConfig = wxPayConfigService.getWxPayConfig(request.getTenantId());

            // 构建预支付请求
            PrepayRequest prepayRequest = buildPrepayRequest(request, orderNo, paymentConfig);

            // 调用微信支付API
            PrepayResponse prepayResponse = callWechatPayApi(prepayRequest, wxPayConfig);

            // 构建响应
            PaymentResponse response = PaymentResponse.wechatNative(
                orderNo, prepayResponse.getCodeUrl(), request.getAmount(), request.getTenantId());
            response.setUserId(request.getUserId());

            // 确保orderNo被正确设置
            response.setOrderNo(orderNo);

            // 调试日志：检查响应对象的orderNo
            log.info("构建的响应对象 - orderNo: {}, codeUrl: {}, success: {}",
                response.getOrderNo(), response.getCodeUrl(), response.getSuccess());

            log.info("{}, 支付类型: {}, 租户ID: {}, 订单号: {}, 金额: {}",
                PaymentConstants.LogMessage.PAYMENT_SUCCESS, getSupportedPaymentType(),
                request.getTenantId(), orderNo, request.getFormattedAmount());

            return response;

        } catch (PaymentException e) {
            log.error("{}, 支付类型: {}, 租户ID: {}, 错误: {}",
                PaymentConstants.LogMessage.PAYMENT_FAILED, getSupportedPaymentType(),
                request.getTenantId(), e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("{}, 支付类型: {}, 租户ID: {}, 系统错误: {}",
                PaymentConstants.LogMessage.PAYMENT_FAILED, getSupportedPaymentType(),
                request.getTenantId(), e.getMessage(), e);
            throw PaymentException.systemError("微信Native支付创建失败: " + e.getMessage(), e);
        }
    }

    @Override
    public PaymentResponse queryPayment(String orderNo, Integer tenantId) throws PaymentException {
        log.info("开始查询微信Native支付状态, 订单号: {}, 租户ID: {}", orderNo, tenantId);

        try {
            // 参数验证
            if (!StringUtils.hasText(orderNo)) {
                throw PaymentException.paramError("订单号不能为空");
            }
            if (tenantId == null) {
                throw PaymentException.paramError("租户ID不能为空");
            }

            // 获取支付配置（包含商户号等信息）
            Payment paymentConfig = wxPayConfigService.getPaymentConfigForStrategy(tenantId);

            // 获取微信支付配置
            Config wxPayConfig = wxPayConfigService.getWxPayConfig(tenantId);

            // 调用微信支付查询API
            return queryWechatPaymentStatus(orderNo, tenantId, paymentConfig, wxPayConfig);

        } catch (Exception e) {
            if (e instanceof PaymentException) {
                throw e;
            }
            log.error("查询微信Native支付状态失败, 订单号: {}, 租户ID: {}, 错误: {}",
                orderNo, tenantId, e.getMessage(), e);
            throw PaymentException.systemError("查询微信支付状态失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String handleNotify(Map<String, String> headers, String body, Integer tenantId) throws PaymentException {
        log.info("{}, 支付类型: {}, 租户ID: {}",
            PaymentConstants.LogMessage.NOTIFY_START, getSupportedPaymentType(), tenantId);

        try {
            // 委托给专门的回调处理服务
            return wxPayNotifyService.handlePaymentNotify(headers, body, tenantId);
        } catch (Exception e) {
            log.error("{}, 支付类型: {}, 租户ID: {}, 错误: {}",
                PaymentConstants.LogMessage.NOTIFY_FAILED, getSupportedPaymentType(),
                tenantId, e.getMessage(), e);
            throw PaymentException.systemError("微信支付回调处理失败: " + e.getMessage(), e);
        }
    }

    @Override
    public PaymentResponse refund(String orderNo, String refundNo, BigDecimal totalAmount,
                                 BigDecimal refundAmount, String reason, Integer tenantId) throws PaymentException {
        // TODO: 实现微信支付退款逻辑
        throw PaymentException.unsupportedPayment("暂不支持微信支付退款", PaymentType.WECHAT_NATIVE);
    }

    @Override
    public PaymentResponse queryRefund(String refundNo, Integer tenantId) throws PaymentException {
        // TODO: 实现微信退款查询逻辑
        throw PaymentException.unsupportedPayment("暂不支持微信退款查询", PaymentType.WECHAT_NATIVE);
    }

    @Override
    public boolean closeOrder(String orderNo, Integer tenantId) throws PaymentException {
        // TODO: 实现微信订单关闭逻辑
        throw PaymentException.unsupportedPayment("暂不支持微信订单关闭", PaymentType.WECHAT_NATIVE);
    }

    @Override
    public boolean supportRefund() {
        return true;
    }

    @Override
    public boolean supportQuery() {
        return true;
    }

    @Override
    public boolean supportClose() {
        return true;
    }

    @Override
    public boolean needNotify() {
        return true;
    }

    /**
     * 生成订单号（使用雪花算法保证全局唯一）
     */
    private String generateOrderNo(PaymentRequest request) {
        if (StringUtils.hasText(request.getOrderNo())) {
            return request.getOrderNo();
        }
        return Long.toString(IdUtil.getSnowflakeNextId());
    }



    /**
     * 构建微信预支付请求
     */
    private PrepayRequest buildPrepayRequest(PaymentRequest request, String orderNo, Payment paymentConfig) {
        PrepayRequest prepayRequest = new PrepayRequest();

        // 设置应用ID和商户号（关键修复）
        prepayRequest.setAppid(paymentConfig.getAppId());
        prepayRequest.setMchid(paymentConfig.getMchId());

        // 设置金额
        Amount amount = new Amount();
        amount.setTotal(request.getAmountInCents());
        amount.setCurrency(PaymentConstants.Wechat.CURRENCY);
        prepayRequest.setAmount(amount);

        // 设置基本信息
        prepayRequest.setOutTradeNo(orderNo);
        prepayRequest.setDescription(request.getEffectiveDescription());

        log.info("创建微信支付订单 - 订单号: {}, 商户号: {}, 金额: {}分",
            orderNo, paymentConfig.getMchId(), request.getAmountInCents());

        // 设置回调URL（必填字段）
        String notifyUrl = null;
        if (StringUtils.hasText(request.getNotifyUrl())) {
            // 优先使用请求中的回调URL
            notifyUrl = request.getNotifyUrl();
        } else if (StringUtils.hasText(paymentConfig.getNotifyUrl())) {
            // 使用配置中的回调URL
            notifyUrl = paymentConfig.getNotifyUrl();
        } else {
            // 如果都没有，抛出异常
            throw new RuntimeException("回调通知地址不能为空，请在支付请求中设置notifyUrl或在支付配置中设置notifyUrl");
        }
        prepayRequest.setNotifyUrl(notifyUrl);

        log.debug("构建微信预支付请求完成, 订单号: {}, 金额: {}分, AppID: {}, 商户号: {}, 回调URL: {}",
            orderNo, request.getAmountInCents(), paymentConfig.getAppId(), paymentConfig.getMchId(), notifyUrl);

        return prepayRequest;
    }

    /**
     * 查询微信支付状态
     */
    private PaymentResponse queryWechatPaymentStatus(String orderNo, Integer tenantId, Payment paymentConfig, Config wxPayConfig) throws PaymentException {
        try {
            log.info("开始查询微信支付状态 - 订单号: {}, 商户号: {}, 租户ID: {}",
                orderNo, paymentConfig.getMchId(), tenantId);

            // 构建查询请求
            QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
            queryRequest.setOutTradeNo(orderNo);
            queryRequest.setMchid(paymentConfig.getMchId());

            // 构建服务
            NativePayService service = new NativePayService.Builder().config(wxPayConfig).build();

            // 调用查询接口
            Transaction transaction = service.queryOrderByOutTradeNo(queryRequest);

            if (transaction == null) {
                throw PaymentException.systemError("微信支付查询返回空结果", null);
            }

            // 转换支付状态
            PaymentStatus paymentStatus = convertWechatPaymentStatus(transaction.getTradeState());

            // 构建响应
            PaymentResponse response = new PaymentResponse();
            response.setSuccess(true);
            response.setOrderNo(orderNo);
            response.setPaymentStatus(paymentStatus);
            response.setTenantId(tenantId);
            response.setPaymentType(PaymentType.WECHAT_NATIVE);

            if (transaction.getAmount() != null) {
                // 微信返回的金额是分，需要转换为元
                BigDecimal amount = new BigDecimal(transaction.getAmount().getTotal()).divide(new BigDecimal("100"));
                response.setAmount(amount);
            }

            if (transaction.getTransactionId() != null) {
                response.setTransactionId(transaction.getTransactionId());
            }

            log.info("微信Native支付状态查询成功, 订单号: {}, 状态: {}, 微信交易号: {}",
                orderNo, paymentStatus, transaction.getTransactionId());

            return response;

        } catch (Exception e) {
            if (e instanceof PaymentException) {
                throw e;
            }
            log.error("查询微信支付状态失败, 订单号: {}, 错误: {}", orderNo, e.getMessage(), e);
            throw PaymentException.networkError("查询微信支付状态失败: " + e.getMessage(), PaymentType.WECHAT_NATIVE, e);
        }
    }

    /**
     * 转换微信支付状态
     */
    private PaymentStatus convertWechatPaymentStatus(Transaction.TradeStateEnum tradeState) {
        if (tradeState == null) {
            return PaymentStatus.PENDING;
        }

        switch (tradeState) {
            case SUCCESS:
                return PaymentStatus.SUCCESS;
            case REFUND:
                return PaymentStatus.REFUNDED;
            case NOTPAY:
                return PaymentStatus.PENDING;
            case CLOSED:
                return PaymentStatus.CANCELLED;
            case REVOKED:
                return PaymentStatus.CANCELLED;
            case USERPAYING:
                return PaymentStatus.PROCESSING;
            case PAYERROR:
                return PaymentStatus.FAILED;
            default:
                return PaymentStatus.PENDING;
        }
    }

    /**
     * 调用微信支付API
     */
    private PrepayResponse callWechatPayApi(PrepayRequest request, Config wxPayConfig) throws PaymentException {
        try {
            // 构建服务
            NativePayService service = new NativePayService.Builder().config(wxPayConfig).build();

            // 调用预支付接口
            PrepayResponse response = service.prepay(request);

            if (response == null || !StringUtils.hasText(response.getCodeUrl())) {
                throw PaymentException.networkError("微信支付API返回数据异常", PaymentType.WECHAT_NATIVE, null);
            }

            log.debug("微信支付API调用成功, 订单号: {}", request.getOutTradeNo());
            return response;

        } catch (Exception e) {
            if (e instanceof PaymentException) {
                throw e;
            }
            throw PaymentException.networkError("调用微信支付API失败: " + e.getMessage(), PaymentType.WECHAT_NATIVE, e);
        }
    }
}
