package com.cnooc.expert.common.exception;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * 通用业务自定义异常
 * 适用于参数校验、业务规则冲突、权限校验等所有业务层面的异常场景
 */
@Getter
@Slf4j
public class BusinessException extends RuntimeException {

    // ------------------- Getter 方法（仅提供获取，不允许修改） -------------------
    /**
     * 错误码（标准化，如：40001=参数错误，40301=权限不足，50001=系统异常）
     * 建议遵循 HTTP 状态码规范，扩展业务子码（如 400 开头为客户端错误，500 开头为服务端错误）
     */
    private final Integer errorCode;

    /**
     * 业务场景标识（如："user_register"=用户注册，"order_pay"=订单支付，便于定位异常来源）
     */
    private final String businessScene;

    /**
     * 异常关联数据（可选，存储导致异常的关键业务数据，如：{"userId":"10086","phone":"13800138000"}）
     */
    private final Map<String, Object> errorData;

    // ------------------- 构造方法（按场景重载） -------------------

    /**
     * 基础构造器：仅包含错误信息（适用于简单场景）
     * @param message 异常描述信息
     */
    public BusinessException(String message) {
        super(message);
        this.errorCode = 500; // 默认错误码
        this.businessScene = "系统错误";   // 默认未知场景
        this.errorData = null;

        // 记录日志
        log.error("BusinessException occurred: {}", message);
    }

    /**
     * 构造器：带错误码+错误信息（最常用，标准化异常响应）
     * @param errorCode 错误码（如："40001"）
     * @param message 异常描述信息
     */
    public BusinessException(Integer errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
        this.businessScene = "UNKNOWN";
        this.errorData = null;

        // 记录日志
        log.error("BusinessException occurred - Code: {}, Message: {}", errorCode, message);
    }

    /**
     * 构造器：带错误码+错误信息+业务场景（精准定位异常来源）
     * @param errorCode 错误码
     * @param message 异常描述信息
     * @param businessScene 业务场景（如："user_login"）
     */
    public BusinessException(Integer errorCode, String message, String businessScene) {
        super(message);
        this.errorCode = errorCode;
        this.businessScene = businessScene;
        this.errorData = null;

        // 记录日志
        log.error("BusinessException occurred - Code: {}, Scene: {}, Message: {}",
                errorCode, businessScene, message);
    }

    /**
     * 构造器：带完整信息（错误码+信息+场景+异常数据，便于排查）
     * @param errorCode 错误码
     * @param message 异常描述信息
     * @param businessScene 业务场景
     * @param errorData 异常关联数据（如错误的参数、用户ID等）
     */
    public BusinessException(Integer errorCode, String message, String businessScene, Map<String, Object> errorData) {
        super(message);
        this.errorCode = errorCode;
        this.businessScene = businessScene;
        this.errorData = errorData;

        // 记录日志
        log.error("BusinessException occurred - Code: {}, Scene: {}, Message: {}, Data: {}",
                errorCode, businessScene, message, errorData);
    }

    /**
     * 构造器：带根因异常（用于包装底层异常，如SQL异常、IO异常）
     * @param errorCode 错误码
     * @param message 异常描述信息
     * @param cause 根因异常（底层原始异常）
     */
    public BusinessException(Integer errorCode, String message, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
        this.businessScene = "UNKNOWN";
        this.errorData = null;

        // 记录日志
        log.error("BusinessException occurred - Code: {}, Message: {}, Cause: {}",
                errorCode, message, cause.getClass().getSimpleName());
    }

    /**
     * 构造器：全参数（适配复杂场景）
     * @param errorCode 错误码
     * @param message 异常描述信息
     * @param businessScene 业务场景
     * @param errorData 异常关联数据
     * @param cause 根因异常
     */
    public BusinessException(Integer errorCode, String message, String businessScene, Map<String, Object> errorData, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
        this.businessScene = businessScene;
        this.errorData = errorData;

        // 记录日志
        log.error("BusinessException occurred - Code: {}, Scene: {}, Message: {}, Data: {}, Cause: {}",
                errorCode, businessScene, message, errorData, cause.getClass().getSimpleName());
    }

    // ------------------- 增强异常信息可读性 -------------------
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("BusinessException: [");
        sb.append("errorCode=").append(errorCode)
                .append(", businessScene=").append(businessScene)
                .append(", message=").append(getMessage()).append("]");

        // 追加异常数据（若存在）
        if (errorData != null && !errorData.isEmpty()) {
            sb.append(" | errorData=").append(errorData);
        }

        // 追加根因异常（若存在）
        if (getCause() != null) {
            sb.append(" | cause=").append(getCause().getClass().getSimpleName());
        }

        return sb.toString();
    }
}