//! Trust registry specific errors.

use thiserror::Error;

use super::HttpError;
use crate::trust_registry::IssuerStatus;

/// Trust registry specific errors.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum TrustRegistryError {
    /// Issuer not found in trust registry
    #[error("Issuer not found: {0}")]
    IssuerNotFound(String),

    /// Issuer status is invalid (suspended or revoked)
    #[error("Issuer status invalid: {status:?}")]
    InvalidIssuerStatus {
        /// The invalid status
        status: IssuerStatus,
    },

    /// Credential type not permitted for issuer
    #[error("Credential type '{credential_type}' not permitted for issuer '{issuer_did}'")]
    CredentialTypeNotPermitted {
        /// The credential type requested
        credential_type: String,
        /// The issuer DID
        issuer_did: String,
    },

    /// HTTP error from trust registry API
    #[error("HTTP error: {0}")]
    Http(#[from] HttpError),

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

impl TrustRegistryError {
    /// Check if this error is retryable.
    #[must_use]
    pub const fn is_retryable(&self) -> bool {
        match self {
            Self::Http(e) => e.is_retryable(),
            Self::IssuerNotFound(_)
            | Self::InvalidIssuerStatus { .. }
            | Self::CredentialTypeNotPermitted { .. }
            | Self::Cache(_) => false,
        }
    }

    /// Create an issuer not found error.
    #[must_use]
    pub fn issuer_not_found(did: impl Into<String>) -> Self {
        Self::IssuerNotFound(did.into())
    }

    /// Create an invalid issuer status error.
    #[must_use]
    pub const fn invalid_status(status: IssuerStatus) -> Self {
        Self::InvalidIssuerStatus { status }
    }

    /// Create a credential type not permitted error.
    #[must_use]
    pub fn credential_not_permitted(
        credential_type: impl Into<String>,
        issuer_did: impl Into<String>,
    ) -> Self {
        Self::CredentialTypeNotPermitted {
            credential_type: credential_type.into(),
            issuer_did: issuer_did.into(),
        }
    }

    /// Create a cache error.
    #[must_use]
    pub fn cache(message: impl Into<String>) -> Self {
        Self::Cache(message.into())
    }

    /// Get suggested retry delay in milliseconds.
    ///
    /// Returns `Some(delay)` for retryable errors, `None` otherwise.
    /// Delegates to inner `HttpError` for HTTP-related errors.
    #[must_use]
    pub const fn suggested_retry_delay_ms(&self) -> Option<u64> {
        match self {
            Self::Http(e) => e.suggested_retry_delay_ms(),
            // Non-retryable errors don't have a suggested delay
            Self::IssuerNotFound(_)
            | Self::InvalidIssuerStatus { .. }
            | Self::CredentialTypeNotPermitted { .. }
            | Self::Cache(_) => None,
        }
    }

    /// Get the error category for metrics and logging.
    #[must_use]
    pub const fn category(&self) -> &'static str {
        match self {
            Self::IssuerNotFound(_) => "issuer_not_found",
            Self::InvalidIssuerStatus { .. } => "invalid_issuer_status",
            Self::CredentialTypeNotPermitted { .. } => "credential_type_not_permitted",
            Self::Http(_) => "http",
            Self::Cache(_) => "cache",
        }
    }
}
