use thiserror::Error;

/// Errors that can occur during optimization solving
#[derive(Error, Debug, Clone, PartialEq)]
pub enum OptimizationError {
    #[error("The problem is infeasible - no solution exists")]
    Infeasible,

    #[error("The problem is unbounded - the objective function can be improved indefinitely")]
    Unbounded,

    #[error("Numerical instability detected: {reason}")]
    NumericalInstability { reason: String },

    #[error("Invalid problem formulation: {reason}")]
    InvalidProblem { reason: String },

    #[error("Solver configuration error: {reason}")]
    SolverError { reason: String },

    #[error("Maximum iterations reached ({max_iter}) without convergence")]
    MaxIterationsReached { max_iter: usize },

    #[error("Degenerate solution detected")]
    Degenerate,

    #[error("Cycling detected in simplex algorithm")]
    Cycling,
}

/// Errors that can occur during problem construction or validation
#[derive(Error, Debug, Clone, PartialEq)]
pub enum ProblemError {
    #[error("Dimension mismatch: expected {expected} variables but got {actual}")]
    DimensionMismatch { expected: usize, actual: usize },

    #[error("Empty problem: no variables defined")]
    EmptyProblem,

    #[error("Invalid variable bounds: lower bound {lower} > upper bound {upper}")]
    InvalidBounds { lower: f64, upper: f64 },

    #[error("Invalid constraint coefficients: length {actual} doesn't match number of variables {expected}")]
    InvalidConstraintLength { expected: usize, actual: usize },

    #[error("Variable name '{name}' already exists")]
    DuplicateVariableName { name: String },

    #[error("Invalid constraint: {reason}")]
    InvalidConstraint { reason: String },

    #[error("Invalid objective: {reason}")]
    InvalidObjective { reason: String },
}

/// Errors that can occur during parsing
#[derive(Error, Debug, Clone, PartialEq)]
pub enum ParseError {
    #[error("Failed to parse file: {reason}")]
    ParseError { reason: String },

    #[error("Unsupported format: {format}")]
    UnsupportedFormat { format: String },

    #[error("IO error: {reason}")]
    IoError { reason: String },

    #[error("Invalid syntax at line {line}: {reason}")]
    SyntaxError { line: usize, reason: String },
}

/// Main result type for the library
pub type Result<T> = std::result::Result<T, OptimizationError>;

/// Result type for problem construction
pub type ProblemResult<T> = std::result::Result<T, ProblemError>;

/// Result type for parsing operations
pub type ParseResult<T> = std::result::Result<T, ParseError>;