//! Error types for FlashDNS

use thiserror::Error;

/// Result type for FlashDNS operations
pub type Result<T> = std::result::Result<T, Error>;

/// Error types for DNS operations
#[derive(Debug, Error)]
pub enum Error {
    #[error("zone not found: {0}")]
    ZoneNotFound(String),

    #[error("zone already exists: {0}")]
    ZoneAlreadyExists(String),

    #[error("record not found: {zone}/{name}/{record_type}")]
    RecordNotFound {
        zone: String,
        name: String,
        record_type: String,
    },

    #[error("invalid zone name: {0}")]
    InvalidZoneName(String),

    #[error("invalid record name: {0}")]
    InvalidRecordName(String),

    #[error("invalid record data: {0}")]
    InvalidRecordData(String),

    #[error("access denied: {0}")]
    AccessDenied(String),

    #[error("invalid argument: {0}")]
    InvalidArgument(String),

    #[error("invalid input: {0}")]
    InvalidInput(String),

    #[error("storage error: {0}")]
    StorageError(String),

    #[error("internal error: {0}")]
    Internal(String),
}

impl Error {
    /// Returns DNS RCODE for this error
    pub fn rcode(&self) -> u8 {
        match self {
            Error::ZoneNotFound(_) => 3,      // NXDOMAIN
            Error::RecordNotFound { .. } => 3, // NXDOMAIN
            Error::AccessDenied(_) => 5,       // REFUSED
            Error::InvalidArgument(_) => 1,    // FORMERR
            Error::InvalidInput(_) => 1,       // FORMERR
            _ => 2,                            // SERVFAIL
        }
    }
}
