//! Compile-time assertion that the new `SvAware` bound on
//! `SessionStore::AuthContext` is enforced by the type system.
//!
//! If a consumer forgets to `impl SvAware for ConsumerAuth`, this test
//! would fail to compile — the bound is the contract.

#![cfg(feature = "axum")]

use pas_external::middleware::{NewSession, SessionStore, SvAware};
use pas_external::types::SessionId;
use std::convert::Infallible;
use std::future::Future;

#[derive(Clone)]
struct TestCtx {
    ppnum_id: String,
    sv: Option<i64>,
}

impl SvAware for TestCtx {
    fn ppnum_id(&self) -> &str {
        &self.ppnum_id
    }
    fn sv(&self) -> Option<i64> {
        self.sv
    }
}

#[derive(Debug)]
struct NeverError;

impl std::fmt::Display for NeverError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "never")
    }
}
impl std::error::Error for NeverError {}

#[derive(Default)]
struct TestStore;

impl SessionStore for TestStore {
    type Error = NeverError;
    type AuthContext = TestCtx;

    fn create(&self, _: NewSession) -> impl Future<Output = Result<SessionId, Self::Error>> + Send {
        async { Ok(SessionId("test".to_string())) }
    }
    fn find(
        &self,
        _: &SessionId,
    ) -> impl Future<Output = Result<Option<TestCtx>, Self::Error>> + Send {
        async { Ok(None) }
    }
    fn delete(&self, _: &SessionId) -> impl Future<Output = Result<(), Self::Error>> + Send {
        async { Ok(()) }
    }
    fn update_sv(
        &self,
        _: &SessionId,
        _: i64,
    ) -> impl Future<Output = Result<(), Self::Error>> + Send {
        async { Ok(()) }
    }
}

/// Compile-only check — `S::AuthContext: SvAware` bound is enforced.
fn _assert_bound<S: SessionStore>() -> impl FnOnce(S::AuthContext) -> (Option<i64>, String) {
    |ctx| (ctx.sv(), ctx.ppnum_id().to_string())
}

#[test]
fn sv_aware_bound_compiles() {
    let _ = _assert_bound::<TestStore>();
    // Use Infallible from std to ensure it's not flagged as unused
    let _: Result<(), Infallible> = Ok(());
}

#[test]
fn sv_aware_returns_expected_values() {
    let ctx = TestCtx {
        ppnum_id: "01HZXY12345678901234567890".to_string(),
        sv: Some(7),
    };
    assert_eq!(ctx.ppnum_id(), "01HZXY12345678901234567890");
    assert_eq!(ctx.sv(), Some(7));
}

#[test]
fn sv_aware_handles_none_for_agent() {
    let ctx = TestCtx {
        ppnum_id: "01H1234567890123456789AGENT".to_string(),
        sv: None,
    };
    assert_eq!(ctx.sv(), None, "agent tokens have no sv claim");
}
