package com.gxwebsoft.payment.exception;

import com.gxwebsoft.payment.enums.PaymentType;

/**
 * 支付异常基类
 * 统一处理支付相关的业务异常
 *
 * @author 科技小王子
 * @since 2025-01-26
 */
public class PaymentException extends Exception {

    private static final long serialVersionUID = 1L;

    /**
     * 错误代码
     */
    private String errorCode;

    /**
     * 支付类型
     */
    private PaymentType paymentType;

    /**
     * 租户ID
     */
    private Integer tenantId;

    /**
     * 订单号
     */
    private String orderNo;

    public PaymentException(String message) {
        super(message);
    }

    public PaymentException(String message, Throwable cause) {
        super(message, cause);
    }

    public PaymentException(String errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }

    public PaymentException(String errorCode, String message, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
    }

    public PaymentException(String errorCode, String message, PaymentType paymentType) {
        super(message);
        this.errorCode = errorCode;
        this.paymentType = paymentType;
    }

    public PaymentException(String errorCode, String message, PaymentType paymentType, Integer tenantId) {
        super(message);
        this.errorCode = errorCode;
        this.paymentType = paymentType;
        this.tenantId = tenantId;
    }

    public PaymentException(String errorCode, String message, PaymentType paymentType, Integer tenantId, String orderNo) {
        super(message);
        this.errorCode = errorCode;
        this.paymentType = paymentType;
        this.tenantId = tenantId;
        this.orderNo = orderNo;
    }

    // Getters and Setters
    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public PaymentType getPaymentType() {
        return paymentType;
    }

    public void setPaymentType(PaymentType paymentType) {
        this.paymentType = paymentType;
    }

    public Integer getTenantId() {
        return tenantId;
    }

    public void setTenantId(Integer tenantId) {
        this.tenantId = tenantId;
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("PaymentException{");
        if (errorCode != null) {
            sb.append("errorCode='").append(errorCode).append("', ");
        }
        if (paymentType != null) {
            sb.append("paymentType=").append(paymentType).append(", ");
        }
        if (tenantId != null) {
            sb.append("tenantId=").append(tenantId).append(", ");
        }
        if (orderNo != null) {
            sb.append("orderNo='").append(orderNo).append("', ");
        }
        sb.append("message='").append(getMessage()).append("'");
        sb.append("}");
        return sb.toString();
    }

    /**
     * 支付错误代码常量
     */
    public static class ErrorCode {
        /** 参数错误 */
        public static final String PARAM_ERROR = "PARAM_ERROR";
        /** 配置错误 */
        public static final String CONFIG_ERROR = "CONFIG_ERROR";
        /** 证书错误 */
        public static final String CERTIFICATE_ERROR = "CERTIFICATE_ERROR";
        /** 网络错误 */
        public static final String NETWORK_ERROR = "NETWORK_ERROR";
        /** 签名错误 */
        public static final String SIGNATURE_ERROR = "SIGNATURE_ERROR";
        /** 金额错误 */
        public static final String AMOUNT_ERROR = "AMOUNT_ERROR";
        /** 订单错误 */
        public static final String ORDER_ERROR = "ORDER_ERROR";
        /** 状态错误 */
        public static final String STATUS_ERROR = "STATUS_ERROR";
        /** 余额不足 */
        public static final String INSUFFICIENT_BALANCE = "INSUFFICIENT_BALANCE";
        /** 支付超时 */
        public static final String TIMEOUT_ERROR = "TIMEOUT_ERROR";
        /** 重复支付 */
        public static final String DUPLICATE_PAYMENT = "DUPLICATE_PAYMENT";
        /** 不支持的支付方式 */
        public static final String UNSUPPORTED_PAYMENT = "UNSUPPORTED_PAYMENT";
        /** 系统错误 */
        public static final String SYSTEM_ERROR = "SYSTEM_ERROR";
    }

    // 静态工厂方法
    public static PaymentException paramError(String message) {
        return new PaymentException(ErrorCode.PARAM_ERROR, message);
    }

    public static PaymentException configError(String message, PaymentType paymentType, Integer tenantId) {
        return new PaymentException(ErrorCode.CONFIG_ERROR, message, paymentType, tenantId);
    }

    public static PaymentException certificateError(String message, PaymentType paymentType) {
        return new PaymentException(ErrorCode.CERTIFICATE_ERROR, message, paymentType);
    }

    public static PaymentException networkError(String message, PaymentType paymentType, Throwable cause) {
        return new PaymentException(ErrorCode.NETWORK_ERROR, message, cause);
    }

    public static PaymentException signatureError(String message, PaymentType paymentType) {
        return new PaymentException(ErrorCode.SIGNATURE_ERROR, message, paymentType);
    }

    public static PaymentException amountError(String message) {
        return new PaymentException(ErrorCode.AMOUNT_ERROR, message);
    }

    public static PaymentException orderError(String message, String orderNo) {
        PaymentException exception = new PaymentException(ErrorCode.ORDER_ERROR, message);
        exception.setOrderNo(orderNo);
        return exception;
    }

    public static PaymentException statusError(String message, String orderNo) {
        PaymentException exception = new PaymentException(ErrorCode.STATUS_ERROR, message);
        exception.setOrderNo(orderNo);
        return exception;
    }

    public static PaymentException insufficientBalance(String message, Integer tenantId) {
        return new PaymentException(ErrorCode.INSUFFICIENT_BALANCE, message, PaymentType.BALANCE, tenantId);
    }

    public static PaymentException timeoutError(String message, PaymentType paymentType, String orderNo) {
        PaymentException exception = new PaymentException(ErrorCode.TIMEOUT_ERROR, message, paymentType);
        exception.setOrderNo(orderNo);
        return exception;
    }

    public static PaymentException duplicatePayment(String message, String orderNo) {
        PaymentException exception = new PaymentException(ErrorCode.DUPLICATE_PAYMENT, message);
        exception.setOrderNo(orderNo);
        return exception;
    }

    public static PaymentException unsupportedPayment(String message, PaymentType paymentType) {
        return new PaymentException(ErrorCode.UNSUPPORTED_PAYMENT, message, paymentType);
    }

    public static PaymentException systemError(String message, Throwable cause) {
        return new PaymentException(ErrorCode.SYSTEM_ERROR, message, cause);
    }
}
