use chrono::Utc;
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation, decode, encode};

use crate::models::{Claims, TempTokenClaims};
use actix_web::{
    Error, HttpMessage, body::MessageBody, dev::ServiceRequest, dev::ServiceResponse,
    middleware::Next,
}; // 新增：用于包装中间件函数

// 中间件函数：泛型 B 约束为 MessageBody，返回 Result<ServiceResponse<B>, Error>
pub async fn jwt_middleware<B: MessageBody>(
    req: ServiceRequest,
    next: Next<B>,
) -> Result<ServiceResponse<B>, Error> {
    // （保持原有逻辑不变）
    let auth_header = req
        .headers()
        .get("Authorization")
        .ok_or_else(|| actix_web::error::ErrorUnauthorized("缺少Authorization头"))?
        .to_str()
        .map_err(|_| actix_web::error::ErrorUnauthorized("Authorization格式无效"))?;

    let token = auth_header.strip_prefix("Bearer ").ok_or_else(|| {
        actix_web::error::ErrorUnauthorized("Authorization格式应为 Bearer <token>")
    })?;

    let jwt_secret = std::env::var("JWT_SECRET")
        .map_err(|_| actix_web::error::ErrorInternalServerError("服务器未配置JWT密钥"))?;

    let claims = verify_token(token, &jwt_secret)
        .map_err(|e| actix_web::error::ErrorUnauthorized(format!("无效的token: {}", e)))?;

    req.extensions_mut().insert(claims);
    next.call(req).await
}

// 生成JWT的函数
pub fn generate_token(
    user_id: i32,
    openid: &str,
    user_type: i32,
    secret: &str,
) -> Result<String, String> {
    // 设置过期时间：当前时间 + 24小时（86400秒）
    let now = Utc::now();
    let exp = (now + chrono::Duration::hours(24)).timestamp();
    let iat = now.timestamp();

    // 构建Claims
    let claims = Claims {
        exp,
        iat,
        user_id,
        openid: openid.to_string(),
        user_type,
    };

    // 生成token
    encode(
        &Header::new(Algorithm::HS256), // 使用HS256算法
        &claims,
        &EncodingKey::from_secret(secret.as_bytes()), // 签名密钥
    )
    .map_err(|e| format!("生成JWT失败: {}", e))
}

// 验证并解析JWT的函数
pub fn verify_token(token: &str, secret: &str) -> Result<Claims, String> {
    // 验证配置（指定算法，默认会检查exp等字段）
    let validation = Validation::new(Algorithm::HS256);

    // 解析token
    let decoded = decode::<Claims>(
        token,
        &DecodingKey::from_secret(secret.as_bytes()), // 与签发时相同的密钥
        &validation,
    )
    .map_err(|e| format!("JWT验证失败: {}", e))?;

    Ok(decoded.claims)
}

// 生成临时token（包含openid和resource_id，短期有效）
pub fn generate_temp_token(
    openid: &str,
    resource_id: i32,
    secret: &str,
    expire_minutes: i64, // 有效期（分钟）
) -> Result<String, String> {
    let now = Utc::now();
    let exp = (now + chrono::Duration::minutes(expire_minutes)).timestamp();
    let iat = now.timestamp();

    let claims = TempTokenClaims {
        exp,
        iat,
        openid: openid.to_string(),
        resource_id,
    };

    encode(
        &Header::new(Algorithm::HS256),
        &claims,
        &EncodingKey::from_secret(secret.as_bytes()),
    )
    .map_err(|e| format!("生成临时token失败: {}", e))
}

// 验证临时token并返回载荷
pub fn verify_temp_token(token: &str, secret: &str) -> Result<TempTokenClaims, String> {
    let validation = Validation::new(Algorithm::HS256);
    let decoded = decode::<TempTokenClaims>(
        token,
        &DecodingKey::from_secret(secret.as_bytes()),
        &validation,
    )
    .map_err(|e| format!("临时token验证失败: {}", e))?;

    Ok(decoded.claims)
}
