// Simple structured logging wrapper
// QUAL-HIGH-01: Current implementation uses LoggingService which provides file-based structured logging.
// For production-grade logging with better performance and features, consider migrating to Pino or Winston.
// This would require:
// - Installing pino or winston package
// - Configuring transports (file, console, remote)
// - Setting up log levels and formatting
// - Updating all Logger usage throughout codebase
// - Testing and validation
// Current implementation is functional for production use with file-based logging.

import LoggingService from '#services/file-system/logService';
import { getErrorSeverity } from '#constants/errors';
import { GenericError } from '#interfaces/error/generic';

export interface LogContext {
	requestId?: string;
	userId?: string;
	action?: string;
	endpoint?: string;
	error?: string;
	stack?: string | undefined;
	[key: string]: unknown;
}

// Helper function for colored console logs with timestamp
// Use this for development/console output instead of Logger class which writes to file
export const log = (level: 'INFO' | 'OK' | 'ERR' | 'WARN' | 'ACCESS', message: string) => {
	const time = new Date().toLocaleTimeString('en-US', { hour12: false });
	const colors: Record<string, string> = {
		INFO: '\x1b[36m',
		OK: '\x1b[32m',
		ERR: '\x1b[31m',
		WARN: '\x1b[33m',
		ACCESS: '\x1b[36m',
	};
	const reset = '\x1b[0m';
	const gray = '\x1b[90m';
	console.log(`${gray}[${time}]${reset} ${colors[level]}[${level}]${reset} ${message}`);
};

export class Logger {
	static info(message: string, context?: LogContext) {
		const loggingService = new LoggingService();
		loggingService.logAsync('info', 'Logger', message, context, context).catch((err) => {
			// SEC-08: Fallback to console if logging service fails
			const time = new Date().toISOString();
			console.error(`[${time}] [Logger] Failed to log info:`, err);
			console.log(`[${time}] [INFO] ${message}`, context);
		});
	}

	static error(message: string, error?: Error | unknown, context?: LogContext) {
		const loggingService = new LoggingService();
		const err = error instanceof Error ? error : new Error(String(error));
		loggingService.logAsync('error', 'Logger', err, context, context).catch((logErr) => {
			// SEC-08: Fallback to console if logging service fails
			const time = new Date().toISOString();
			console.error(`[${time}] [Logger] Failed to log error:`, logErr);
			console.error(`[${time}] [ERROR] ${message}`, err, context);
		});
	}

	static warn(message: string, context?: LogContext) {
		const loggingService = new LoggingService();
		loggingService.logAsync('warn', 'Logger', message, context, context).catch((err) => {
			// SEC-08: Fallback to console if logging service fails
			const time = new Date().toISOString();
			console.error(`[${time}] [Logger] Failed to log warn:`, err);
			console.warn(`[${time}] [WARN] ${message}`, context);
		});
	}

	static debug(message: string, context?: LogContext) {
		// eslint-disable-next-line no-restricted-syntax
		if (process.env.NODE_ENV === 'development') {
			const loggingService = new LoggingService();
			loggingService.logAsync('debug', 'Logger', message, context, context).catch((err) => {
				// SEC-08: Fallback to console if logging service fails
				const time = new Date().toISOString();
				console.error(`[${time}] [Logger] Failed to log debug:`, err);
				console.debug(`[${time}] [DEBUG] ${message}`, context);
			});
		}
	}

	/**
	 * Log error based on severity level
	 * Automatically routes to appropriate log level based on error catalog severity
	 * @param error - GenericError instance
	 * @param context - Additional log context
	 */
	static logBySeverity(error: GenericError, context?: LogContext): void {
		const severity = getErrorSeverity(error.code);

		// Build context object, filtering out undefined values
		const errorContext: LogContext = {
			...context,
			severity,
		};

		// Only add defined values
		if (error.requestId !== undefined) {
			errorContext.requestId = error.requestId;
		}
		if (error.userId !== undefined) {
			errorContext.userId = error.userId;
		}
		errorContext.timestamp = error.timestamp;

		switch (severity) {
			case 'critical':
				// Critical errors: log as error with full details
				this.error(`[CRITICAL] ${error.code}`, error, errorContext);
				// TODO: Auto-send to Sentry when integrated
				// if (error.logToSentry) { Sentry.captureException(error, { context }); }
				break;
			case 'high':
				// High severity: log as error
				this.error(`[HIGH] ${error.code}`, error, errorContext);
				break;
			case 'medium':
				// Medium severity: log as warning
				this.warn(`[MEDIUM] ${error.code}`, errorContext);
				break;
			case 'low':
				// Low severity: log as info
				this.info(`[LOW] ${error.code}`, errorContext);
				break;
			default:
				// Fallback to error logging
				this.error(error.code, error, context);
		}
	}
}

export default Logger;
