use crate::utils::i18n::{EN, ZH_CN};
use async_trait::async_trait;
use axum::{
    extract::{FromRequestParts, Request},
    http::{request::Parts, StatusCode},
    middleware::Next,
    response::Response,
};
use std::ops::Deref;

#[derive(Debug, Clone)]
pub struct Language(pub String);
impl Deref for Language {
    type Target = String;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[async_trait]
impl<S: Send + Sync> FromRequestParts<S> for Language {
    type Rejection = (StatusCode, &'static str);
    async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
        parts.extensions.get::<Language>().cloned().ok_or((
            StatusCode::INTERNAL_SERVER_ERROR,
            "language context missing",
        ))
    }
}

pub async fn language_middleware(mut req: Request, next: Next) -> Response {
    let language = req
        .headers()
        .get("Accept-Language")
        .and_then(|v| v.to_str().ok())
        .and_then(|v| v.split(',').next())
        .map(str::trim)
        .filter(|v| *v == ZH_CN || *v == EN)
        .unwrap_or(ZH_CN)
        .to_string();
    req.extensions_mut().insert(Language(language));
    next.run(req).await
}
