//! Error handling for the CLI.

use std::path::PathBuf;
use thiserror::Error;

/// Exit codes for the CLI.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExitCode {
    /// Successful execution.
    Success = 0,
    /// Simulation error (non-convergence, validation failure).
    SimulationError = 1,
    /// Configuration error (invalid JSON, missing fields).
    ConfigError = 2,
    /// I/O error (file not found, permission denied).
    IoError = 3,
}

impl From<ExitCode> for i32 {
    fn from(code: ExitCode) -> i32 {
        code as i32
    }
}

/// CLI-specific errors.
#[derive(Error, Debug)]
pub enum CliError {
    #[error("Configuration error: {0}")]
    Config(String),

    #[error("Configuration file not found: {0}")]
    ConfigNotFound(PathBuf),

    #[error("Invalid configuration file: {0}")]
    InvalidConfig(#[source] serde_json::Error),

    #[error("Simulation error: {0}")]
    Simulation(String),

    #[error("I/O error: {0}")]
    Io(#[from] std::io::Error),

    #[error("Batch directory not found: {0}")]
    BatchDirNotFound(PathBuf),

    #[error("No configuration files found in directory: {0}")]
    NoConfigFiles(PathBuf),

    #[error("Component error: {0}")]
    Component(#[from] entropyk_components::ComponentError),
}

impl CliError {
    pub fn exit_code(&self) -> ExitCode {
        match self {
            CliError::Config(_) | CliError::ConfigNotFound(_) | CliError::InvalidConfig(_) => {
                ExitCode::ConfigError
            }
            CliError::Simulation(_) | CliError::Component(_) => ExitCode::SimulationError,
            CliError::Io(_) | CliError::BatchDirNotFound(_) | CliError::NoConfigFiles(_) => {
                ExitCode::IoError
            }
        }
    }
}

/// Result type for CLI operations.
pub type CliResult<T> = Result<T, CliError>;
