package com.gxwebsoft.payment.service;

import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.payment.dto.PaymentRequest;
import com.gxwebsoft.payment.dto.PaymentResponse;
import com.gxwebsoft.payment.dto.PaymentWithOrderRequest;
import com.gxwebsoft.payment.enums.PaymentType;
import com.gxwebsoft.payment.exception.PaymentException;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 统一支付服务接口
 * 提供所有支付方式的统一入口
 *
 * @author 科技小王子
 * @since 2025-01-26
 */
public interface PaymentService {

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

    /**
     * 创建支付订单（包含订单信息）
     * 统一支付模块：先创建订单，再发起支付
     *
     * @param request   支付与订单创建请求
     * @param loginUser 当前登录用户
     * @return 支付响应
     * @throws PaymentException 创建失败时抛出
     */
    PaymentResponse createPaymentWithOrder(PaymentWithOrderRequest request, User loginUser) throws PaymentException;

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

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

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

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

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

    /**
     * 获取支持的支付类型列表
     *
     * @return 支付类型列表
     */
    List<PaymentType> getSupportedPaymentTypes();

    /**
     * 检查支付类型是否支持
     *
     * @param paymentType 支付类型
     * @return true表示支持
     */
    boolean isPaymentTypeSupported(PaymentType paymentType);

    /**
     * 检查支付类型是否支持退款
     *
     * @param paymentType 支付类型
     * @return true表示支持退款
     */
    boolean isRefundSupported(PaymentType paymentType);

    /**
     * 检查支付类型是否支持查询
     *
     * @param paymentType 支付类型
     * @return true表示支持查询
     */
    boolean isQuerySupported(PaymentType paymentType);

    /**
     * 检查支付类型是否支持关闭订单
     *
     * @param paymentType 支付类型
     * @return true表示支持关闭订单
     */
    boolean isCloseSupported(PaymentType paymentType);

    /**
     * 检查支付类型是否需要异步通知
     *
     * @param paymentType 支付类型
     * @return true表示需要异步通知
     */
    boolean isNotifyNeeded(PaymentType paymentType);

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

    /**
     * 获取支付策略信息
     *
     * @param paymentType 支付类型
     * @return 策略信息Map，包含策略名称、描述等
     */
    Map<String, Object> getPaymentStrategyInfo(PaymentType paymentType);

    /**
     * 获取所有支付策略信息
     *
     * @return 所有策略信息列表
     */
    List<Map<String, Object>> getAllPaymentStrategyInfo();

    /**
     * 检查支付配置
     *
     * @param tenantId 租户ID
     * @return 配置检查结果
     */
    Map<String, Object> checkPaymentConfig(Integer tenantId);
}
