package com.seer.teach.pay.app.client;

import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.enums.pay.PayStatusEnum;
import com.seer.teach.common.exception.CommonException;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.pay.app.client.convert.PayClientConvert;
import com.seer.teach.pay.app.client.dto.PayOrderCallBackRespDTO;
import com.seer.teach.pay.app.client.dto.PayOrderReqDTO;
import com.seer.teach.pay.app.client.dto.PayOrderRespDTO;
import com.seer.teach.pay.app.client.dto.PayRefundReqDTO;
import com.seer.teach.pay.app.client.dto.RefundNotificationRespDTO;
import com.seer.teach.pay.dto.RefundSubmitRespDTO;
import com.seer.teach.pay.entity.PayOrderEntity;
import com.seer.teach.pay.entity.PayOrderExtensionEntity;
import com.seer.teach.pay.service.IPayOrderExtensionService;
import com.seer.teach.pay.service.IPayOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Map;
import java.util.Optional;

/**
 * 抽象支付策略模板
 * 实现支付流程的通用逻辑，具体支付方式只需实现特定的方法
 */
@Slf4j
public abstract class AbstractPayClient implements PayClient {

    @Autowired
    protected IPayOrderService payOrderService;

    @Autowired
    protected IPayOrderExtensionService payOrderExtensionService;


    @Override
    public PayOrderRespDTO payOrder(PayOrderReqDTO payOrderReqDTO) {
        log.info("开始支付订单，渠道：{}，支付订单号：{}", getChannel(), payOrderReqDTO.getPayOrderSn());

        Object extrasRequest = getPrepayRequestParam(payOrderReqDTO);

        PayOrderRespDTO payOrderRespDTO = doPayOrder(payOrderReqDTO, extrasRequest);

        // 查找或创建支付订单扩展信息
        Optional<PayOrderExtensionEntity> extension = payOrderExtensionService.getOneByOrderId(payOrderReqDTO.getParOrderId());

        // 如果扩展信息不存在，则创建
        if (extension.isPresent()) {
            log.info("支付订单扩展信息不存在，创建新的扩展信息");
            updatePayOrderExtension(extension.get(), payOrderRespDTO);
        } else {
            PayOrderExtensionEntity orderExtension = createPayOrderExtension(payOrderReqDTO);
            boolean extensionSaved = payOrderExtensionService.save(orderExtension);
            log.info("保存支付订单扩展信息结果：{}", extensionSaved);
        }

        log.info("支付订单创建成功，订单号：{}", payOrderReqDTO.getParOrderId());
        return payOrderRespDTO;
    }

    @Override
    public PayOrderRespDTO handlePayCallback(Map<String, String> headers, Map<String, String> params, String body) {
        log.info("开始处理支付回调，渠道：{}", getChannel());
        // 解析支付回调
        PayOrderCallBackRespDTO payOrderCallBackRespDTO = parseOrderNotify(headers, params, body);

        PayOrderEntity payOrder = payOrderService.getOrderByOrderSn(payOrderCallBackRespDTO.getPayOrderSn());
        AssertUtils.notNull(payOrder, ResultCodeEnum.PAY_ORDER_IS_NOT_EXIST);

        if (PayStatusEnum.SUCCESS.getCode() == payOrderCallBackRespDTO.getPayStatus().getCode()) {
            log.info("该笔支付已处理，订单号：{}", payOrderCallBackRespDTO.getPayOrderSn());
            throw new CommonException(ResultCodeEnum.PAY_ORDER_IS_PROCESSED);
        }
        return PayClientConvert.INSTANCE.convert(payOrderCallBackRespDTO);
    }

    /**
     * 创建支付订单扩展信息
     */
    private PayOrderExtensionEntity createPayOrderExtension(PayOrderReqDTO payOrderReqDTO) {
        PayOrderExtensionEntity extension = new PayOrderExtensionEntity();
        extension.setOrderId(payOrderReqDTO.getParOrderId());
        extension.setMerchantOrderSn(payOrderReqDTO.getMerchantOrderSn());
        return extension;
    }

    /**
     * 更新支付订单扩展信息
     */
    private void updatePayOrderExtension(PayOrderExtensionEntity extension, PayOrderRespDTO payOrderRespDTO) {
        if (payOrderRespDTO.getPrepayId() != null || payOrderRespDTO.getPayParams() != null) {
            // 将 payParams 对象转换为 JSON 字符串存储
            String channelExtras = null;
            if (payOrderRespDTO.getPayParams() != null) {
                try {
                    channelExtras = cn.hutool.json.JSONUtil.toJsonStr(payOrderRespDTO.getPayParams());
                } catch (Exception e) {
                    channelExtras = payOrderRespDTO.getPayParams().toString();
                }
            }
            extension.setChannelExtras(channelExtras);
            payOrderExtensionService.updateById(extension);
        }
    }

    protected abstract PayOrderCallBackRespDTO parseOrderNotify(Map<String, String> headers, Map<String, String> params, String body);

    protected abstract Object getPrepayRequestParam(PayOrderReqDTO payOrderReq);

    /**
     * 具体支付渠道实现创建预支付订单
     */
    protected abstract PayOrderRespDTO doPayOrder(PayOrderReqDTO payOrderReqDTO , Object extrasRequest);

    /**
     * 具体支付渠道实现查询支付状态
     */
    protected abstract PayOrderEntity doQueryPayStatus(String orderSn);

    /**
     * 具体支付渠道实现关闭支付订单
     */
    protected abstract boolean doClosePayOrder(String orderSn);


    protected abstract RefundSubmitRespDTO doRefundOrder(PayRefundReqDTO payRefundReqDTO);


    protected abstract Optional<RefundNotificationRespDTO> parseRefundNotify(Map<String, String> headers, Map<String, String> params, String body);

    @Override
    public RefundSubmitRespDTO refundOrder(PayRefundReqDTO payRefundReqDTO){
        return doRefundOrder(payRefundReqDTO);
    }

    @Override
    public PayOrderEntity queryPayStatus(String orderSn) {
        return doQueryPayStatus(orderSn);
    }

    @Override
    public boolean closePayOrder(String orderSn) {
        return doClosePayOrder(orderSn);
    }

    public Optional<RefundNotificationRespDTO> handleRefundCallback(Map<String, String> headers, Map<String, String> params, String body) {
        log.info("开始处理统一退款回调");
        Optional<RefundNotificationRespDTO> refundNotificationRespDTO = parseRefundNotify(headers, params, body);
        if (!refundNotificationRespDTO.isPresent()) {
            throw new CommonException(ResultCodeEnum.REFUND_NOTIFY_PARSE_ERROR);
        }
        return refundNotificationRespDTO;
    }

}