//! LLM Key Server — OIDC identity to temporary scoped API keys.
//!
//! This module implements the key server pattern described in RFC-0043:
//!
//! 1. **Token Exchange**: Accept an OIDC identity token (`POST /auth/token`),
//!    verify it against a configured OIDC issuer, map the identity to scopes
//!    via the policy engine, and return a short-lived opaque bearer token.
//!
//! 2. **Validation**: The auth middleware calls [`KeyServer::validate_token`] as
//!    a secondary validation path after the static key check.
//!
//! 3. **Revocation**: `DELETE /auth/token/{jti}` revokes a specific token instantly.
//!    Admin endpoints are guarded by a separate `admin.bearer_token`.
//!
//! 4. **Audit**: Every token lifecycle event is emitted via `tracing::info!` with
//!    structured fields queryable by any log aggregator.
//!
//! # Architecture
//!
//! ```text
//! Request arrives
//!   -> Extract bearer token
//!   -> Try static auth (existing ResolvedAuthConfig)  -- O(n) key comparison
//!   -> Try temporary token (KeyServer.validate_token) -- O(1) DashMap lookup
//!   -> Reject
//! ```
//!
//! The key server is **opt-in**: set `key_server.enabled: true` in the gateway
//! configuration. When disabled, no overhead is incurred.

pub mod audit;
pub mod handler;
pub mod oidc;
pub mod policy;
pub mod store;

use std::sync::Arc;

use crate::config::KeyServerConfig;
use crate::gateway::auth::AuthenticatedClient;

pub use audit::AuditEvent;
pub use oidc::{JwksCache, OidcVerifier};
pub use policy::PolicyEngine;
pub use store::{InMemoryTokenStore, TemporaryToken, TokenStore};

/// The key server — central coordinator for OIDC token exchange.
///
/// Holds all subsystems and exposes the two methods called from the
/// auth middleware: [`validate_token`](KeyServer::validate_token) and
/// the HTTP handlers in [`handler`].
pub struct KeyServer {
    /// Token store (in-memory `DashMap`)
    pub store: Arc<dyn TokenStore>,
    /// OIDC verifier (JWKS cache + signature verification)
    pub oidc: Arc<OidcVerifier>,
    /// Access policy engine
    pub policy: Arc<PolicyEngine>,
    /// Key server configuration
    pub config: KeyServerConfig,
}

impl KeyServer {
    /// Create a new key server from configuration.
    #[must_use]
    pub fn new(config: KeyServerConfig) -> Self {
        let store = Arc::new(InMemoryTokenStore::new());
        let oidc = Arc::new(OidcVerifier::new(config.oidc.clone()));
        let policy = Arc::new(PolicyEngine::new(config.policies.clone()));

        Self {
            store,
            oidc,
            policy,
            config,
        }
    }

    /// Validate a bearer token from an incoming request.
    ///
    /// Returns the [`AuthenticatedClient`] and the associated [`TemporaryToken`]
    /// if the token is valid and not expired/revoked. Returns `None` otherwise.
    pub async fn validate_token(
        &self,
        token: &str,
    ) -> Option<(AuthenticatedClient, TemporaryToken)> {
        let temp = self.store.get(token).await?;

        let client = AuthenticatedClient {
            name: temp.identity.email.clone(),
            rate_limit: temp.scopes.rate_limit,
            backends: temp.scopes.backends.clone(),
            allowed_tools: if temp.scopes.tools.is_empty() {
                None
            } else {
                Some(temp.scopes.tools.clone())
            },
            denied_tools: None,
        };

        let ev = AuditEvent::used(&temp, None);
        audit::emit(&ev);

        Some((client, temp))
    }
}
