pub type Result<T> = std::result::Result<T, TloxError>;

#[derive(Debug)]
pub enum TloxError {
    Database(rusqlite::Error),
    InvalidTarget(String),
    Io(std::io::Error),
    InvalidTimestamp(std::time::SystemTimeError),
    MissingApiKey,
    AnthropicApi(String),
    /// Auth-related failure: missing token, invalid token, expired session.
    Auth(String),
    /// HTTP client/network failure talking to the cloud (Convex).
    Network(String),
}

impl std::fmt::Display for TloxError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Database(error) => write!(f, "database error: {error}"),
            Self::InvalidTarget(target) => write!(f, "invalid target: {target}"),
            Self::Io(error) => write!(f, "i/o error: {error}"),
            Self::InvalidTimestamp(error) => write!(f, "timestamp error: {error}"),
            Self::MissingApiKey => write!(f, "ANTHROPIC_API_KEY is not set"),
            Self::AnthropicApi(message) => write!(f, "{message}"),
            Self::Auth(message) => write!(f, "{message}"),
            Self::Network(message) => write!(f, "{message}"),
        }
    }
}

impl std::error::Error for TloxError {}

impl From<rusqlite::Error> for TloxError {
    fn from(error: rusqlite::Error) -> Self {
        Self::Database(error)
    }
}

impl From<std::io::Error> for TloxError {
    fn from(error: std::io::Error) -> Self {
        Self::Io(error)
    }
}

impl From<std::time::SystemTimeError> for TloxError {
    fn from(error: std::time::SystemTimeError) -> Self {
        Self::InvalidTimestamp(error)
    }
}
