package com.fizz.business.utils;

import com.fizz.business.constants.enums.ExceptionCodeEnum;
import org.springframework.stereotype.Component;

/**
 * Global business exception class for error data handling
 */

@Component
public class ErrorDataException extends RuntimeException {
    private final ExceptionCodeEnum codeEnum;
    private Object errorData;

    // ================ Basic Constructors ================

    public ErrorDataException() {
        super(ExceptionCodeEnum.ERROR.getMessage());
        this.codeEnum = ExceptionCodeEnum.ERROR;
    }

    public ErrorDataException(String message) {
        super(message);
        this.codeEnum = ExceptionCodeEnum.ERROR;
    }

    public ErrorDataException(Throwable cause) {
        super(ExceptionCodeEnum.ERROR.getMessage(), cause);
        this.codeEnum = ExceptionCodeEnum.ERROR;
    }

    public ErrorDataException(String message, Throwable cause) {
        super(message, cause);
        this.codeEnum = ExceptionCodeEnum.ERROR;
    }

    // ================ Full Feature Constructors ================

    public ErrorDataException(ExceptionCodeEnum codeEnum) {
        super(codeEnum.getMessage());
        this.codeEnum = codeEnum;
    }

    public ErrorDataException(ExceptionCodeEnum codeEnum, String extendMessage) {
        super(combineMessage(codeEnum, extendMessage));
        this.codeEnum = codeEnum;
    }

    public ErrorDataException(ExceptionCodeEnum codeEnum, Throwable cause) {
        super(codeEnum.getMessage(), cause);
        this.codeEnum = codeEnum;
    }

    public ErrorDataException(ExceptionCodeEnum codeEnum, String extendMessage, Throwable cause) {
        super(combineMessage(codeEnum, extendMessage), cause);
        this.codeEnum = codeEnum;
    }

    // ================ With Error Data Constructors ================

    public ErrorDataException(ExceptionCodeEnum codeEnum, Object errorData) {
        super(codeEnum.getMessage());
        this.codeEnum = codeEnum;
        this.errorData = errorData;
    }

    public ErrorDataException(ExceptionCodeEnum codeEnum, String extendMessage, Object errorData) {
        super(combineMessage(codeEnum, extendMessage));
        this.codeEnum = codeEnum;
        this.errorData = errorData;
    }

    public ErrorDataException(ExceptionCodeEnum codeEnum, Throwable cause, Object errorData) {
        super(codeEnum.getMessage(), cause);
        this.codeEnum = codeEnum;
        this.errorData = errorData;
    }

    public ErrorDataException(ExceptionCodeEnum codeEnum, String extendMessage, Throwable cause, Object errorData) {
        super(combineMessage(codeEnum, extendMessage), cause);
        this.codeEnum = codeEnum;
        this.errorData = errorData;
    }

    // ================ Helper Methods ================

    private static String combineMessage(ExceptionCodeEnum codeEnum, String extendMessage) {
        return String.format("%s: %s", codeEnum.getMessage(), extendMessage);
    }

    // ================ Getters ================

    public ExceptionCodeEnum getCodeEnum() {
        return codeEnum;
    }

    public Object getErrorData() {
        return errorData;
    }

    // ================ Override Methods ================

    @Override
    public String toString() {
        return String.format("ErrorDataException{code=%s, message='%s', errorData=%s}",
                codeEnum.getCode(), getMessage(), errorData);
    }
}
