package com.gxwebsoft.payment.strategy;

import com.gxwebsoft.payment.dto.PaymentRequest;
import com.gxwebsoft.payment.dto.PaymentResponse;
import com.gxwebsoft.payment.enums.PaymentType;
import com.gxwebsoft.payment.exception.PaymentException;

import java.util.Map;

/**
 * 支付策略接口
 * 定义所有支付方式的统一接口
 *
 * @author 科技小王子
 * @since 2025-01-26
 */
public interface PaymentStrategy {

    /**
     * 获取支持的支付类型
     *
     * @return 支付类型
     */
    PaymentType getSupportedPaymentType();

    /**
     * 验证支付请求参数
     *
     * @param request 支付请求
     * @throws PaymentException 参数验证失败时抛出
     */
    void validateRequest(PaymentRequest request) throws PaymentException;

    /**
     * 创建支付订单
     *
     * @param request 支付请求
     * @return 支付响应
     * @throws PaymentException 支付创建失败时抛出
     */
    PaymentResponse createPayment(PaymentRequest request) throws PaymentException;

    /**
     * 查询支付状态
     *
     * @param orderNo  订单号
     * @param tenantId 租户ID
     * @return 支付响应
     * @throws PaymentException 查询失败时抛出
     */
    PaymentResponse queryPayment(String orderNo, Integer tenantId) throws PaymentException;

    /**
     * 处理支付回调通知
     *
     * @param headers  请求头
     * @param body     请求体
     * @param tenantId 租户ID
     * @return 处理结果，返回给第三方的响应内容
     * @throws PaymentException 处理失败时抛出
     */
    String handleNotify(Map<String, String> headers, String body, Integer tenantId) throws PaymentException;

    /**
     * 申请退款
     *
     * @param orderNo     订单号
     * @param refundNo    退款单号
     * @param totalAmount 订单总金额
     * @param refundAmount 退款金额
     * @param reason      退款原因
     * @param tenantId    租户ID
     * @return 退款响应
     * @throws PaymentException 退款申请失败时抛出
     */
    PaymentResponse refund(String orderNo, String refundNo, 
                          java.math.BigDecimal totalAmount, java.math.BigDecimal refundAmount, 
                          String reason, Integer tenantId) throws PaymentException;

    /**
     * 查询退款状态
     *
     * @param refundNo 退款单号
     * @param tenantId 租户ID
     * @return 退款查询响应
     * @throws PaymentException 查询失败时抛出
     */
    PaymentResponse queryRefund(String refundNo, Integer tenantId) throws PaymentException;

    /**
     * 关闭订单
     *
     * @param orderNo  订单号
     * @param tenantId 租户ID
     * @return 关闭结果
     * @throws PaymentException 关闭失败时抛出
     */
    boolean closeOrder(String orderNo, Integer tenantId) throws PaymentException;

    /**
     * 是否支持退款
     *
     * @return true表示支持退款
     */
    default boolean supportRefund() {
        return false;
    }

    /**
     * 是否支持查询
     *
     * @return true表示支持查询
     */
    default boolean supportQuery() {
        return false;
    }

    /**
     * 是否支持关闭订单
     *
     * @return true表示支持关闭订单
     */
    default boolean supportClose() {
        return false;
    }

    /**
     * 是否需要异步通知
     *
     * @return true表示需要异步通知
     */
    default boolean needNotify() {
        return false;
    }

    /**
     * 获取策略名称
     *
     * @return 策略名称
     */
    default String getStrategyName() {
        return getSupportedPaymentType().getName();
    }

    /**
     * 获取策略描述
     *
     * @return 策略描述
     */
    default String getStrategyDescription() {
        return getSupportedPaymentType().getName() + "支付策略";
    }
}
