use miette::Diagnostic;
use thiserror::Error;

#[derive(Debug, Error, Diagnostic)]
pub enum CliError {
    #[error("Configuration error: {0}")]
    Config(#[source] Box<dyn std::error::Error + Send + Sync>),

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

    #[error("Failed to parse URL: {0}")]
    Url(#[from] url::ParseError),

    #[error("Failed to parse JSON: {0}")]
    Json(#[from] serde_json::Error),

    #[error("Failed to parse TOML: {0}")]
    Toml(#[from] toml::de::Error),

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

    #[error("IndieWeb error: {0}")]
    IndieWeb(#[source] indieweb::Error),

    #[error("Token not found. Run 'auth' first or provide --token")]
    TokenNotFound,

    #[error("Authorization failed: {0}")]
    AuthFailed(String),

    #[error("Authorization cancelled by user")]
    AuthCancelled,

    #[error("No authorization endpoint found for {0}")]
    NoAuthEndpoint(String),

    #[error("No token endpoint found for {0}")]
    NoTokenEndpoint(String),

    #[error("Token revocation failed")]
    RevocationFailed,

    #[error("Invalid scope: {0}")]
    InvalidScope(String),
}

impl From<indieweb::Error> for CliError {
    fn from(e: indieweb::Error) -> Self {
        CliError::IndieWeb(e)
    }
}

impl From<http::Error> for CliError {
    fn from(e: http::Error) -> Self {
        CliError::Http(e.to_string())
    }
}

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