//! Error types for ClickType

use std::io;
use thiserror::Error;

/// Result type alias using ClickType's Error
pub type Result<T> = std::result::Result<T, Error>;

/// Main error type for ClickType operations
#[derive(Debug, Error)]
pub enum Error {
    /// I/O error
    #[error("I/O error: {0}")]
    Io(#[from] io::Error),

    /// Serialization error
    #[error("Write error: {0}")]
    Write(#[from] WriteError),

    /// Deserialization error
    #[error("Read error: {0}")]
    Read(#[from] ReadError),

    /// Invalid type conversion
    #[error("Type error: {0}")]
    Type(String),

    /// Invalid configuration
    #[error("Configuration error: {0}")]
    Config(String),
}

/// Errors that occur during writing/serialization
#[derive(Debug, Error)]
pub enum WriteError {
    /// I/O error during write
    #[error("I/O error: {0}")]
    Io(#[from] io::Error),

    /// Invalid value for the target type
    #[error("Invalid value: {0}")]
    InvalidValue(String),

    /// Buffer overflow
    #[error("Buffer overflow: attempted to write {attempted} bytes, capacity is {capacity}")]
    BufferOverflow {
        /// Attempted bytes to write
        attempted: usize,
        /// Buffer capacity
        capacity: usize,
    },
}

/// Errors that occur during reading/deserialization
#[derive(Debug, Error)]
pub enum ReadError {
    /// I/O error during read
    #[error("I/O error: {0}")]
    Io(#[from] io::Error),

    /// Unexpected EOF
    #[error("Unexpected end of input")]
    UnexpectedEof,

    /// Invalid data format
    #[error("Invalid format: {0}")]
    InvalidFormat(String),

    /// Invalid enum variant
    #[error("Invalid enum variant: {0}")]
    InvalidVariant(i8),
}

impl From<std::string::FromUtf8Error> for ReadError {
    fn from(err: std::string::FromUtf8Error) -> Self {
        Self::InvalidFormat(format!("Invalid UTF-8: {}", err))
    }
}
