use axum::{
    extract::FromRequestParts,
    http::request::Parts,
    response::{IntoResponse, Redirect, Response},
};
use tower_sessions::Session;

use irc_now_common::auth::UserClaims;

pub struct AuthUser(pub UserClaims);

impl FromRequestParts<crate::state::AppState> for AuthUser {
    type Rejection = Response;

    async fn from_request_parts(
        parts: &mut Parts,
        state: &crate::state::AppState,
    ) -> Result<Self, Self::Rejection> {
        let session = Session::from_request_parts(parts, state)
            .await
            .map_err(|_| login_redirect(parts))?;

        let claims: Option<UserClaims> = session
            .get("user")
            .await
            .unwrap_or(None);

        match claims {
            Some(c) => Ok(AuthUser(c)),
            None => Err(login_redirect(parts)),
        }
    }
}

fn login_redirect(parts: &Parts) -> Response {
    if parts.headers.get("hx-request").is_some() {
        (
            [(
                axum::http::header::HeaderName::from_static("hx-redirect"),
                axum::http::header::HeaderValue::from_static("/auth/login"),
            )],
            "",
        )
            .into_response()
    } else {
        Redirect::temporary("/auth/login").into_response()
    }
}
