//! Policy, Compliance, and Analysis Errors

use axum::http::StatusCode;
use thiserror::Error;

/// Policy and compliance specific errors
#[derive(Error, Debug, Clone)]
pub enum PolicyError {
    /// Policy evaluation error
    #[error("Policy evaluation error: {0}")]
    Evaluation(String),

    /// Policy parsing error
    #[error("Policy parsing error: {0}")]
    Parsing(String),

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

    /// Compliance check failed
    #[error("Compliance check failed: {0}")]
    Compliance(String),

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

    /// Analysis failed error
    #[error("Analysis failed: {0}")]
    AnalysisFailed(String),
}

impl PolicyError {
    pub fn status_code(&self) -> StatusCode {
        match self {
            Self::Evaluation(_) => StatusCode::INTERNAL_SERVER_ERROR,
            Self::Parsing(_) => StatusCode::BAD_REQUEST,
            Self::Cedar(_) => StatusCode::INTERNAL_SERVER_ERROR,
            Self::Compliance(_) => StatusCode::FORBIDDEN,
            Self::Anomaly(_) => StatusCode::INTERNAL_SERVER_ERROR,
            Self::AnalysisFailed(_) => StatusCode::BAD_REQUEST,
        }
    }

    pub fn error_code(&self) -> &'static str {
        match self {
            Self::Evaluation(_) => "POLICY_EVALUATION_ERROR",
            Self::Parsing(_) => "POLICY_PARSING_ERROR",
            Self::Cedar(_) => "CEDAR_ERROR",
            Self::Compliance(_) => "COMPLIANCE_ERROR",
            Self::Anomaly(_) => "ANOMALY_ERROR",
            Self::AnalysisFailed(_) => "ANALYSIS_FAILED",
        }
    }

    pub fn should_log_error(&self) -> bool {
        true // All policy errors should be logged at ERROR level
    }
}

// Conversions from external policy errors
impl From<cedar_policy::ParseError> for PolicyError {
    fn from(err: cedar_policy::ParseError) -> Self {
        PolicyError::Cedar(err.to_string())
    }
}

impl From<cedar_policy::PolicySetError> for PolicyError {
    fn from(err: cedar_policy::PolicySetError) -> Self {
        PolicyError::Cedar(err.to_string())
    }
}
