/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.common.exception;

import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import lombok.Getter;

/**
 * `YamiShopBindException` 是一个自定义的运行时异常类，用于在项目中表示特定的业务绑定异常情况，
 * 它继承自 `RuntimeException`，意味着在抛出该异常时，不需要显式地在方法声明中添加 `throws` 子句（除非方法本身已经声明了抛出更宽泛的异常类型），
 * 方便在业务逻辑中根据具体情况灵活抛出异常来表示业务流程中的错误或不符合预期的情况，并且可以携带一些额外的信息（如状态码、关联对象等）方便进行异常处理和信息反馈。
 *
 * @author lanhai
 */
@Getter
public class YamiShopBindException extends RuntimeException {

    /**
     * 用于序列化的版本号，在进行对象序列化和反序列化时，这个版本号用于确保序列化的兼容性，
     * 如果类的结构发生变化（例如添加、删除字段等），合适的版本号管理有助于避免反序列化时出现问题，
     * 这里默认生成了一个固定的版本号值，通常在实际项目中，如果类的结构有变更且涉及到序列化操作时，可能需要根据情况更新这个版本号。
     */
    private static final long serialVersionUID = -4137688758944857209L;

    /**
     * 用于存储 HTTP 状态码的属性，通过这个属性可以在异常抛出时传递对应的 HTTP 状态码信息，
     * 方便在统一的异常处理机制中根据状态码来决定返回给客户端的相应状态以及错误提示等内容，
     * 例如可以根据不同的状态码返回不同格式的错误响应，让前端更好地识别和处理异常情况。
     */
    private String code;

    /**
     * 用于存储一个额外的对象的属性，这个对象可以是与异常相关的任意类型的对象，比如在某些业务场景下，
     * 可以将引发异常的相关业务数据对象或者详细的错误信息对象等存放在这里，方便在异常处理时获取更详细的上下文信息进行进一步的分析和处理。
     */
    private Object object;

    /**
     * 用于存储一个 `ServerResponseEntity` 类型对象的属性，`ServerResponseEntity` 可能是项目中自定义的用于封装服务器响应信息的类，
     * 通过这个属性可以直接将一个完整的服务器响应实体对象与异常关联起来，例如在异常处理中可以直接返回这个关联的响应实体给客户端，
     * 提供更丰富、准确的错误响应内容。
     */
    private ServerResponseEntity<?> serverResponseEntity;

    /**
     * 构造函数，根据传入的 `ResponseEnum` 枚举类型参数来初始化异常对象，
     * 会调用父类（`RuntimeException`）的构造函数，将 `ResponseEnum` 中定义的错误消息（`getMsg()` 方法获取）作为异常消息传递给父类，
     * 同时将 `ResponseEnum` 中定义的对应值（`value()` 方法获取）作为 HTTP 状态码赋值给当前异常对象的 `code` 属性，
     * 常用于根据预定义的响应枚举类型来抛出异常，确保异常的状态码和消息符合项目中统一的规范。
     *
     * @param responseEnum 包含了状态码和错误消息等信息的响应枚举类型，用于初始化异常对象的相关属性。
     */
    public YamiShopBindException(ResponseEnum responseEnum) {
        super(responseEnum.getMsg());
        this.code = responseEnum.value();
    }

    /**
     * 构造函数，根据传入的 `ResponseEnum` 枚举类型参数和自定义的错误消息来初始化异常对象，
     * 同样会调用父类（`RuntimeException`）的构造函数，将传入的自定义错误消息 `msg` 作为异常消息传递给父类，
     * 并将 `ResponseEnum` 中定义的对应值（`value()` 方法获取）作为 HTTP 状态码赋值给当前异常对象的 `code` 属性，
     * 适用于在遵循预定义的响应枚举类型的状态码规范基础上，需要自定义具体错误消息的场景，比如针对特定业务逻辑下的更详细错误描述。
     *
     * @param responseEnum 包含了状态码相关信息的响应枚举类型，用于获取状态码赋值给当前异常对象的 `code` 属性。
     * @param msg 自定义的错误消息，用于作为异常消息传递给父类（`RuntimeException`）构造函数。
     */
    public YamiShopBindException(ResponseEnum responseEnum, String msg) {
        super(msg);
        this.code = responseEnum.value();
    }

    /**
     * 构造函数，根据传入的 `ServerResponseEntity` 类型对象来初始化异常对象，
     * 将传入的 `ServerResponseEntity` 对象赋值给当前异常对象的 `serverResponseEntity` 属性，
     * 常用于在已经构建好一个完整的服务器响应实体对象的情况下，将其与异常关联起来，方便在异常处理时直接使用该响应实体进行返回等操作。
     *
     * @param serverResponseEntity 包含了服务器响应信息的对象，用于赋值给当前异常对象的 `serverResponseEntity` 属性。
     */
    public YamiShopBindException(ServerResponseEntity<?> serverResponseEntity) {
        this.serverResponseEntity = serverResponseEntity;
    }

    /**
     * 构造函数，根据传入的自定义错误消息来初始化异常对象，
     * 调用父类（`RuntimeException`）的构造函数，将传入的错误消息 `msg` 作为异常消息传递给父类，
     * 同时将默认的 HTTP 状态码（通过 `ResponseEnum.SHOW_FAIL.value()` 获取）赋值给当前异常对象的 `code` 属性，
     * 用于在没有对应预定义的响应枚举类型或者不需要特定枚举类型关联的情况下，简单地抛出一个带有自定义消息的异常，并赋予默认的状态码。
     *
     * @param msg 自定义的错误消息，用于作为异常消息传递给父类（`RuntimeException`）构造函数，并作为异常的主要描述信息。
     */
    public YamiShopBindException(String msg) {
        super(msg);
        this.code = ResponseEnum.SHOW_FAIL.value();
    }

    /**
     * 构造函数，根据传入的自定义错误消息和一个额外的对象来初始化异常对象，
     * 调用父类（`RuntimeException`）的构造函数，将传入的错误消息 `msg` 作为异常消息传递给父类，
     * 将默认的 HTTP 状态码（通过 `ResponseEnum.SHOW_FAIL.value()` 获取）赋值给当前异常对象的 `code` 属性，
     * 并将传入的额外对象赋值给当前异常对象的 `object` 属性，
     * 适用于在抛出异常时，除了传递错误消息外，还希望携带一个与异常相关的具体对象，方便后续异常处理时获取更多详细信息的场景。
     *
     * @param msg 自定义的错误消息，用于作为异常消息传递给父类（`RuntimeException`）构造函数，并作为异常的主要描述信息。
     * @param object 与异常相关的额外对象，用于赋值给当前异常对象的 `object` 属性，方便后续异常处理时获取更多详细信息。
     */
    public YamiShopBindException(String msg, Object object) {
        super(msg);
        this.code = ResponseEnum.SHOW_FAIL.value();
        this.object = object;
    }
}