package com.gxwebsoft.payment.service;


import com.gxwebsoft.payment.constants.PaymentConstants;
import com.gxwebsoft.payment.exception.PaymentException;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.service.ShopOrderService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

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

/**
 * 微信支付回调通知处理服务
 * 负责处理微信支付的异步通知回调
 *
 * @author 科技小王子
 * @since 2025-01-26
 */
@Slf4j
@Service
public class WxPayNotifyService {

    @Resource
    private WxPayConfigService wxPayConfigService;

    @Resource
    private ShopOrderService shopOrderService;

    /**
     * 处理微信支付回调通知
     *
     * @param headers    请求头
     * @param body       请求体
     * @param tenantId   租户ID
     * @return 处理结果响应
     */
    public String handlePaymentNotify(Map<String, String> headers, String body, Integer tenantId) {
        log.info("{}, 租户ID: {}", PaymentConstants.LogMessage.NOTIFY_START, tenantId);

        try {
            // 参数验证
            validateNotifyParams(headers, body, tenantId);

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

            // 解析并验证回调数据
            Transaction transaction = parseAndVerifyNotification(headers, body, wxPayConfig);

            // 处理支付结果
            processPaymentResult(transaction, tenantId);

            log.info("{}, 租户ID: {}, 订单号: {}",
                PaymentConstants.LogMessage.NOTIFY_SUCCESS, tenantId, transaction.getOutTradeNo());

            return "SUCCESS";

        } catch (Exception e) {
            log.error("{}, 租户ID: {}, 错误: {}",
                PaymentConstants.LogMessage.NOTIFY_FAILED, tenantId, e.getMessage(), e);
            return "FAIL";
        }
    }

    /**
     * 验证回调通知参数
     */
    private void validateNotifyParams(Map<String, String> headers, String body, Integer tenantId) throws PaymentException {
        if (tenantId == null) {
            throw PaymentException.paramError("租户ID不能为空");
        }

        if (headers == null || headers.isEmpty()) {
            throw PaymentException.paramError("请求头不能为空");
        }

        if (!StringUtils.hasText(body)) {
            throw PaymentException.paramError("请求体不能为空");
        }

        // 验证必要的微信支付头部信息
        String signature = headers.get("Wechatpay-Signature");
        String timestamp = headers.get("Wechatpay-Timestamp");
        String nonce = headers.get("Wechatpay-Nonce");
        String serial = headers.get("Wechatpay-Serial");

        if (!StringUtils.hasText(signature)) {
            throw PaymentException.paramError("微信支付签名不能为空");
        }

        if (!StringUtils.hasText(timestamp)) {
            throw PaymentException.paramError("微信支付时间戳不能为空");
        }

        if (!StringUtils.hasText(nonce)) {
            throw PaymentException.paramError("微信支付随机数不能为空");
        }

        if (!StringUtils.hasText(serial)) {
            throw PaymentException.paramError("微信支付序列号不能为空");
        }

        log.debug("回调通知参数验证通过, 租户ID: {}", tenantId);
    }

    /**
     * 解析并验证回调通知
     */
    private Transaction parseAndVerifyNotification(Map<String, String> headers, String body, Config wxPayConfig) throws PaymentException {
        if (wxPayConfig == null) {
            throw PaymentException.systemError("微信支付配置为空", null);
        }

        try {
            // 构建请求参数
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(headers.get("Wechatpay-Serial"))
                    .nonce(headers.get("Wechatpay-Nonce"))
                    .signature(headers.get("Wechatpay-Signature"))
                    .timestamp(headers.get("Wechatpay-Timestamp"))
                    .body(body)
                    .build();

            // 创建通知解析器
            NotificationParser parser = new NotificationParser((NotificationConfig) wxPayConfig);

            // 解析并验证通知
            Transaction transaction = parser.parse(requestParam, Transaction.class);

            if (transaction == null) {
                throw PaymentException.systemError("解析回调通知失败：transaction为空", null);
            }

            log.debug("回调通知解析成功, 订单号: {}, 交易状态: {}",
                transaction.getOutTradeNo(), transaction.getTradeState());

            return transaction;

        } catch (Exception e) {
            if (e instanceof PaymentException) {
                throw e;
            }
            throw PaymentException.systemError("解析回调通知失败: " + e.getMessage(), e);
        }
    }

    /**
     * 处理支付结果
     */
    private void processPaymentResult(Transaction transaction, Integer tenantId) throws PaymentException {
        String outTradeNo = transaction.getOutTradeNo();
        String tradeState = String.valueOf(transaction.getTradeState());

        if (!StringUtils.hasText(outTradeNo)) {
            throw PaymentException.paramError("商户订单号不能为空");
        }

        // 查询订单
        ShopOrder order = shopOrderService.getByOutTradeNo(outTradeNo);
        if (order == null) {
            throw PaymentException.systemError("订单不存在: " + outTradeNo, null);
        }

        // 验证租户ID
        if (!tenantId.equals(order.getTenantId())) {
            throw PaymentException.paramError("订单租户ID不匹配");
        }

        // 验证订单状态 - 使用Boolean类型的payStatus字段
        if (Boolean.TRUE.equals(order.getPayStatus())) {
            log.info("订单已支付，跳过处理, 订单号: {}", outTradeNo);
            return;
        }

        // 根据交易状态处理
        switch (tradeState) {
            case "SUCCESS":
                handlePaymentSuccess(order, transaction);
                break;
            case "REFUND":
                handlePaymentRefund(order, transaction);
                break;
            case "CLOSED":
            case "REVOKED":
            case "PAYERROR":
                handlePaymentFailed(order, transaction);
                break;
            default:
                log.warn("未处理的交易状态: {}, 订单号: {}", tradeState, outTradeNo);
                break;
        }
    }

    /**
     * 处理支付成功
     */
    private void handlePaymentSuccess(ShopOrder order, Transaction transaction) throws PaymentException {
        try {
            // 验证金额
            validateAmount(order, transaction);

            // 更新订单状态
            order.setPayStatus(true); // 使用Boolean类型
            order.setTransactionId(transaction.getTransactionId());
            order.setPayTime(LocalDateTime.parse(transaction.getSuccessTime()));

            // 使用专门的更新方法，会触发支付成功后的业务逻辑
            shopOrderService.updateByOutTradeNo(order);

            // 推送支付结果通知
            pushPaymentNotification(order, transaction);

            log.info("支付成功处理完成, 订单号: {}, 微信交易号: {}",
                order.getOrderNo(), transaction.getTransactionId());

        } catch (Exception e) {
            throw PaymentException.systemError("处理支付成功回调失败: " + e.getMessage(), e);
        }
    }

    /**
     * 处理支付退款
     */
    private void handlePaymentRefund(ShopOrder order, Transaction transaction) throws PaymentException {
        try {
            log.info("处理支付退款, 订单号: {}, 微信交易号: {}",
                order.getOrderNo(), transaction.getTransactionId());

            // 这里可以添加退款相关的业务逻辑
            // 例如：更新订单状态、处理库存、发送通知等

        } catch (Exception e) {
            throw PaymentException.systemError("处理支付退款回调失败: " + e.getMessage(), e);
        }
    }

    /**
     * 处理支付失败
     */
    private void handlePaymentFailed(ShopOrder order, Transaction transaction) throws PaymentException {
        try {
            log.info("处理支付失败, 订单号: {}, 交易状态: {}",
                order.getOrderNo(), transaction.getTradeState());

            // 这里可以添加支付失败相关的业务逻辑
            // 例如：释放库存、发送通知等

        } catch (Exception e) {
            throw PaymentException.systemError("处理支付失败回调失败: " + e.getMessage(), e);
        }
    }

    /**
     * 验证支付金额
     */
    private void validateAmount(ShopOrder order, Transaction transaction) throws PaymentException {
        if (transaction.getAmount() == null || transaction.getAmount().getTotal() == null) {
            throw PaymentException.amountError("回调通知中金额信息为空");
        }

        // 将订单金额转换为分
        BigDecimal orderAmount = order.getMoney();
        if (orderAmount == null) {
            throw PaymentException.amountError("订单金额为空");
        }

        int orderAmountFen = orderAmount.multiply(new BigDecimal(100)).intValue();
        int callbackAmountFen = transaction.getAmount().getTotal();

        if (orderAmountFen != callbackAmountFen) {
            throw PaymentException.amountError(
                String.format("订单金额不匹配，订单金额: %d分, 回调金额: %d分",
                    orderAmountFen, callbackAmountFen));
        }

        log.debug("金额验证通过, 订单号: {}, 金额: {}分", order.getOrderNo(), orderAmountFen);
    }

    /**
     * 推送支付结果通知
     */
    private void pushPaymentNotification(ShopOrder order, Transaction transaction) {
        try {
            log.info("开始推送支付成功通知, 订单号: {}, 交易号: {}, 用户ID: {}",
                order.getOrderNo(), transaction.getTransactionId(), order.getUserId());

            // 1. 记录支付成功日志
            logPaymentSuccess(order, transaction);

            // 2. 发送支付成功通知（可扩展）
            sendPaymentSuccessNotification(order, transaction);

            // 3. 触发其他业务逻辑（可扩展）
            triggerPostPaymentActions(order, transaction);

            log.info("支付结果通知推送完成, 订单号: {}, 交易号: {}",
                order.getOrderNo(), transaction.getTransactionId());
        } catch (Exception e) {
            log.warn("支付结果通知推送失败, 订单号: {}, 错误: {}", order.getOrderNo(), e.getMessage());
            // 推送失败不影响主流程，只记录日志
        }
    }

    /**
     * 记录支付成功日志
     */
    private void logPaymentSuccess(ShopOrder order, Transaction transaction) {
        try {
            log.info("=== 支付成功详细信息 ===");
            log.info("订单号: {}", order.getOrderNo());
            log.info("微信交易号: {}", transaction.getTransactionId());
            log.info("支付金额: {}元", order.getPayPrice());
            log.info("支付时间: {}", transaction.getSuccessTime());
            log.info("用户ID: {}", order.getUserId());
            log.info("租户ID: {}", order.getTenantId());
            log.info("订单标题: {}", order.getTitle());
            log.info("========================");
        } catch (Exception e) {
            log.warn("记录支付成功日志失败: {}", e.getMessage());
        }
    }

    /**
     * 发送支付成功通知
     */
    private void sendPaymentSuccessNotification(ShopOrder order, Transaction transaction) {
        try {
            // TODO: 实现具体的通知逻辑
            // 1. 发送邮件通知
            // 2. 发送短信通知
            // 3. 站内消息通知
            // 4. 微信模板消息通知

            log.debug("支付成功通知发送完成, 订单号: {}", order.getOrderNo());
        } catch (Exception e) {
            log.warn("发送支付成功通知失败, 订单号: {}, 错误: {}", order.getOrderNo(), e.getMessage());
        }
    }

    /**
     * 触发支付成功后的其他业务逻辑
     */
    private void triggerPostPaymentActions(ShopOrder order, Transaction transaction) {
        try {
            // TODO: 根据业务需求实现
            // 1. 开通网站服务
            // 2. 激活会员权益
            // 3. 发放积分奖励
            // 4. 触发营销活动

            log.debug("支付后业务逻辑触发完成, 订单号: {}", order.getOrderNo());
        } catch (Exception e) {
            log.warn("触发支付后业务逻辑失败, 订单号: {}, 错误: {}", order.getOrderNo(), e.getMessage());
        }
    }
}
