use std::ops::Deref;
use std::sync::Arc;

use compliance_core::DashboardConfig;

use super::database::Database;
use super::keycloak_config::KeycloakConfig;

#[derive(Clone)]
pub struct ServerState(Arc<ServerStateInner>);

impl Deref for ServerState {
    type Target = ServerStateInner;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

pub struct ServerStateInner {
    pub db: Database,
    pub config: DashboardConfig,
    pub agent_api_url: String,
    pub keycloak: Option<&'static KeycloakConfig>,
}

impl From<ServerStateInner> for ServerState {
    fn from(inner: ServerStateInner) -> Self {
        Self(Arc::new(inner))
    }
}

impl<S> axum::extract::FromRequestParts<S> for ServerState
where
    S: Send + Sync,
{
    type Rejection = axum::http::StatusCode;

    async fn from_request_parts(
        parts: &mut axum::http::request::Parts,
        _state: &S,
    ) -> Result<Self, Self::Rejection> {
        parts
            .extensions
            .get::<ServerState>()
            .cloned()
            .ok_or(axum::http::StatusCode::INTERNAL_SERVER_ERROR)
    }
}
