import { GenericErrorHandler } from './ViolationImpl';
import { DatabaseErrorHandler } from '../handler/database-error-handler';
import { GenericErrorHandler as UnifiedGenericErrorHandler } from '../handler/generic-error-handler';
import { ExternalServiceErrorHandler } from '../handler/external-error-handler';
import { IErrorHandler } from '../';

// Interface for Violations
export interface IViolation {
	messages: { [key: string]: string }; // Changed from 'message' to match GenericError
	type: string;
	code: string;
	actor?: string;
	additionalData?: unknown;
}

export type IViolations = IViolation[];

// Error Processor Factory
export class ErrorProcessor {
	private static instance: ErrorProcessor;
	private handlers: IErrorHandler[];

	private constructor() {
		this.handlers = [
			// Priority 1: GenericError - Application errors using error catalog
			// Handles: AuthenticationError, ValidationError, NotFoundError, etc.
			new UnifiedGenericErrorHandler(),

			// Priority 2: Database errors from Sequelize ORM
			// Handles: ValidationError, UniqueConstraintError, ForeignKeyConstraintError, BaseError
			new DatabaseErrorHandler(),

			// Priority 3: External service errors (circuit breaker, third-party APIs)
			// Handles: CircuitBreakerOpenError
			new ExternalServiceErrorHandler(),

			// Priority 4: Fallback for unknown errors (plain Error, unknown types)
			// Handles: Any error not caught by above handlers
			new GenericErrorHandler(),
		];
	}

	public static getInstance(): ErrorProcessor {
		ErrorProcessor.instance ??= new ErrorProcessor();
		return ErrorProcessor.instance;
	}

	process(error: unknown, additionalData: Record<string, unknown> = {}): IViolations {
		const handler = this.handlers.find((h) => h.canHandle(error));
		if (!handler) {
			throw new Error('No error handler found for the given error');
		}
		return handler.handle(error, additionalData);
	}
}
