use std::net::SocketAddr;

use api::AppState;
use db::Db;
use server::serve;
use tokio::net::TcpListener;

#[tokio::test]
async fn serves_health_live_over_tcp() {
    let database_url =
        std::env::var("DATABASE_URL").expect("DATABASE_URL must be set for this test");
    let db = Db::connect(&database_url, 2)
        .await
        .expect("connect to database");
    let state = AppState {
        db,
        app_name: "Test".to_string(),
        cookie_secure: false,
        search: None,
        default_language: "sv".into(),
        default_timezone: "Europe/Stockholm".into(),
    };

    let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
    let addr: SocketAddr = listener.local_addr().unwrap();

    let handle = tokio::spawn(async move { serve(listener, state).await });

    let url = format!("http://{addr}/health/live");
    let response = reqwest::get(&url).await;

    // If the request failed and the server task already ended, it errored — surface that
    // (a clear server error) instead of the opaque reqwest failure.
    if response.is_err() && handle.is_finished() {
        match handle.await {
            Ok(Err(err)) => panic!("server failed: {err:?}"),
            other => panic!("server task ended unexpectedly: {other:?}"),
        }
    }

    let body: serde_json::Value = response
        .expect("request succeeds")
        .json()
        .await
        .expect("json body");
    assert_eq!(body["status"], "ok");

    handle.abort();
}
