/**
 * @fileoverview OrdoJS CLI - Error handling utilities
 */

import chalk from 'chalk';
import { logger } from './logger.js';

/**
 * Error types
 */
export enum ErrorType {
  VALIDATION = 'validation',
  COMPILATION = 'compilation',
  RUNTIME = 'runtime',
  SYSTEM = 'system',
  DEPLOYMENT = 'deployment',
  UNKNOWN = 'unknown'
}

/**
 * CLI error class
 */
export class CLIError extends Error {
  constructor(
    message: string,
    public type: ErrorType = ErrorType.UNKNOWN,
    public code?: string,
    public suggestions?: string[]
  ) {
    super(message);
    this.name = 'CLIError';
  }
}

/**
 * Format an error message with line and column information
 */
export function formatErrorWithLocation(
  message: string,
  filePath: string,
  line?: number,
  column?: number
): string {
  const location = line !== undefined ? `${filePath}:${line}${column !== undefined ? `:${column}` : ''}` : filePath;
  return `${chalk.red('error')} ${chalk.gray(location)} ${message}`;
}

/**
 * Format a compilation error
 */
export function formatCompilationError(
  message: string,
  filePath: string,
  line?: number,
  column?: number,
  code?: string,
  suggestions?: string[]
): string {
  let output = formatErrorWithLocation(message, filePath, line, column);

  if (code) {
    output += `\n${chalk.gray(`Error code: ${code}`)}`;
  }

  if (suggestions && suggestions.length > 0) {
    output += '\n\n' + chalk.yellow('Suggestions:');
    suggestions.forEach(suggestion => {
      output += `\n  - ${suggestion}`;
    });
  }

  return output;
}

/**
 * Handle and report errors
 */
export function handleError(error: unknown): never {
  if (error instanceof CLIError) {
    switch (error.type) {
      case ErrorType.VALIDATION:
        logger.error(`Validation error: ${error.message}`);
        break;
      case ErrorType.COMPILATION:
        logger.error(`Compilation error: ${error.message}`);
        break;
      case ErrorType.RUNTIME:
        logger.error(`Runtime error: ${error.message}`);
        break;
      case ErrorType.SYSTEM:
        logger.error(`System error: ${error.message}`);
        break;
      case ErrorType.DEPLOYMENT:
        logger.error(`Deployment error: ${error.message}`);
        break;
      default:
        logger.error(`Error: ${error.message}`);
    }

    if (error.suggestions && error.suggestions.length > 0) {
      logger.info('Suggestions:');
      error.suggestions.forEach(suggestion => {
        logger.info(`  - ${suggestion}`);
      });
    }
  } else if (error instanceof Error) {
    logger.error(`Error: ${error.message}`);
    if (error.stack && process.env.DEBUG) {
      logger.debug(error.stack);
    }
  } else {
    logger.error(`Unknown error: ${String(error)}`);
  }

  process.exit(1);
}
