#![allow(unused_imports)]
use super::*;
use std::collections::HashMap;

fn test_auth_config() -> std::sync::Arc<AuthConfig> {
    std::sync::Arc::new(
        AuthConfig::new("server-test-secret-key-at-least-32-chars")
            .base_url("http://localhost:3000")
            .trusted_origins(vec![
                "http://localhost:5173".to_string(),
                "https://*.vercel.app".to_string(),
                "*suits-formations.v2.athena-auth.com/*".to_string(),
                "suits-formations.v2.athena-auth.com?sslmode=disable".to_string(),
            ]),
    )
}

fn make_options(origin: &str) -> AuthRequest {
    let mut headers = HashMap::new();
    headers.insert("origin".to_string(), origin.to_string());
    AuthRequest {
        method: HttpMethod::Options,
        path: "/sign-in/email".to_string(),
        headers,
        body: None,
        query: HashMap::new(),
        virtual_user_id: None,
    }
}

fn make_get(origin: &str) -> AuthRequest {
    let mut headers = HashMap::new();
    headers.insert("origin".to_string(), origin.to_string());
    AuthRequest {
        method: HttpMethod::Get,
        path: "/get-session".to_string(),
        headers,
        body: None,
        query: HashMap::new(),
        virtual_user_id: None,
    }
}

#[tokio::test]
async fn test_cors_preflight_allowed() {
    let config = CorsConfig::new().allowed_origin("http://localhost:5173");
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = make_options("http://localhost:5173");

    let resp = mw.before_request(&req).await.unwrap();
    assert!(resp.is_some());
    let resp = resp.unwrap();
    assert_eq!(resp.status, 204);
    assert_eq!(
        resp.headers.get("Access-Control-Allow-Origin").unwrap(),
        "http://localhost:5173"
    );
}

#[tokio::test]
async fn test_cors_preflight_default_headers_include_sdk_and_proxy_headers() {
    let config = CorsConfig::new().allowed_origin("http://localhost:5173");
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = make_options("http://localhost:5173");

    let resp = mw.before_request(&req).await.unwrap().unwrap();
    let allowed_headers = resp
        .headers
        .get("Access-Control-Allow-Headers")
        .expect("preflight response should include allowed headers");

    for expected in [
        "X-Athena-Sdk",
        "X-Athena-Tenant",
        "X-Athena-Client",
        "X-Athena-Proxy-Request-Id",
        "X-Request-Id",
    ] {
        assert!(
            allowed_headers.contains(expected),
            "expected '{expected}' in Access-Control-Allow-Headers, got '{allowed_headers}'"
        );
    }
}

#[tokio::test]
async fn test_cors_preflight_not_allowed() {
    let config = CorsConfig::new().allowed_origin("http://localhost:5173");
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = make_options("http://evil.com");

    let resp = mw.before_request(&req).await.unwrap();
    assert!(resp.is_some());
    let resp = resp.unwrap();
    assert_eq!(resp.status, 403);
    let body: serde_json::Value = serde_json::from_slice(&resp.body).unwrap();
    assert_eq!(body["code"], "CORS_ORIGIN_NOT_ALLOWED");
    assert_eq!(body["deliveredOrigin"], "http://evil.com");
    assert_eq!(
        body["suggestedTrustedOriginsEnvLine"],
        "TRUSTED_ORIGINS=http://localhost:5173,https://*.vercel.app,*suits-formations.v2.athena-auth.com/*,suits-formations.v2.athena-auth.com?sslmode=disable,http://evil.com"
    );
}

#[tokio::test]
async fn test_cors_preflight_allows_glob_patterns() {
    let config = CorsConfig::new().allowed_origin("https://*.vercel.app");
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = make_options("https://athena-auth-123.vercel.app");

    let resp = mw.before_request(&req).await.unwrap();
    assert!(resp.is_some());
    let resp = resp.unwrap();
    assert_eq!(resp.status, 204);
    assert_eq!(
        resp.headers.get("Access-Control-Allow-Origin").unwrap(),
        "https://athena-auth-123.vercel.app"
    );
}

#[tokio::test]
async fn test_cors_preflight_defaults_scheme_less_public_globs_to_https() {
    let config = CorsConfig::new().allowed_origin("*suits-formations.v2.athena-auth.com/*");
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = make_options("https://preview-suits-formations.v2.athena-auth.com");

    let resp = mw.before_request(&req).await.unwrap();
    assert!(resp.is_some());
    let resp = resp.unwrap();
    assert_eq!(resp.status, 204);
    assert_eq!(
        resp.headers.get("Access-Control-Allow-Origin").unwrap(),
        "https://preview-suits-formations.v2.athena-auth.com"
    );

    let denied = make_options("http://suits-formations.v2.athena-auth.com");
    let denied_resp = mw.before_request(&denied).await.unwrap().unwrap();
    assert_eq!(denied_resp.status, 403);
}

#[tokio::test]
async fn test_cors_preflight_uses_http_for_cleartext_scheme_hint() {
    let config =
        CorsConfig::new().allowed_origin("suits-formations.v2.athena-auth.com?sslmode=disable");
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = make_options("http://suits-formations.v2.athena-auth.com");

    let resp = mw.before_request(&req).await.unwrap();
    assert!(resp.is_some());
    let resp = resp.unwrap();
    assert_eq!(resp.status, 204);

    let denied = make_options("https://suits-formations.v2.athena-auth.com");
    let denied_resp = mw.before_request(&denied).await.unwrap().unwrap();
    assert_eq!(denied_resp.status, 403);
}

#[tokio::test]
async fn test_cors_adds_headers_after_request() {
    let config = CorsConfig::new().allowed_origin("http://localhost:5173");
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = make_get("http://localhost:5173");

    let response = AuthResponse::json(200, &serde_json::json!({"ok": true})).unwrap();
    let response = mw.after_request(&req, response).await.unwrap();

    assert_eq!(
        response.headers.get("Access-Control-Allow-Origin").unwrap(),
        "http://localhost:5173"
    );
    assert_eq!(
        response
            .headers
            .get("Access-Control-Allow-Credentials")
            .unwrap(),
        "true"
    );
}

#[tokio::test]
async fn test_cors_no_origin_header() {
    let config = CorsConfig::new().allowed_origin("http://localhost:5173");
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = AuthRequest {
        method: HttpMethod::Get,
        path: "/get-session".to_string(),
        headers: HashMap::new(),
        body: None,
        query: HashMap::new(),
        virtual_user_id: None,
    };

    assert!(mw.before_request(&req).await.unwrap().is_none());

    let response = AuthResponse::new(200);
    let response = mw.after_request(&req, response).await.unwrap();
    assert!(!response.headers.contains_key("Access-Control-Allow-Origin"));
}

#[tokio::test]
async fn test_cors_wildcard() {
    let config = CorsConfig::new()
        .allowed_origin("*")
        .allow_credentials(false);
    let mw = CorsMiddleware::new(config, test_auth_config());
    let req = make_get("http://any-origin.com");

    let response = AuthResponse::new(200);
    let response = mw.after_request(&req, response).await.unwrap();
    assert_eq!(
        response.headers.get("Access-Control-Allow-Origin").unwrap(),
        "*"
    );
}
