import { Language } from '../../constants/index';
import { ErrorCode, getErrorEntry, getErrorCategory, ErrorCategory } from '../../constants/errors';

/**
 * Unified Error Class
 *
 * All application errors should use this class or its subclasses.
 * Error codes are sourced from the centralized error catalog.
 */
export class GenericError extends Error {
	messages: Record<Language, string>;
	type: string;
	code: string;
	httpStatus: number;
	category: ErrorCategory;
	additionalData?: unknown;
	requestId?: string;
	userId?: string;
	timestamp: string;
	override stack?: string;

	constructor(errorCode: ErrorCode, additionalData?: unknown, overrideMessage?: Record<Language, string>) {
		// Get error entry from catalog
		const entry = getErrorEntry(errorCode);
		const message = overrideMessage || entry?.message || { en: 'Internal server error', vi: 'Lỗi máy chủ' };
		const httpStatus = entry?.httpStatus || 500;
		const category = getErrorCategory(errorCode);

		// Call parent constructor with default message
		super(message[Language.en]);

		// Set error name to code for better debugging
		this.name = errorCode;

		// Set properties
		this.messages = message;
		this.type = errorCode;
		this.code = errorCode;
		this.httpStatus = httpStatus;
		this.category = category;
		this.additionalData = additionalData;
		this.timestamp = new Date().toISOString();

		// Maintain proper stack trace
		Error.captureStackTrace?.(this, GenericError);
	}

	/**
	 * Create error from error code (factory method)
	 */
	static fromCode(errorCode: ErrorCode, additionalData?: unknown): GenericError {
		return new GenericError(errorCode, additionalData);
	}

	/**
	 * Create error with custom message (factory method)
	 */
	static withMessage(errorCode: ErrorCode, message: Record<Language, string>, additionalData?: unknown): GenericError {
		return new GenericError(errorCode, additionalData, message);
	}
}
