use actix_web::{web, HttpResponse};

use crate::pages::insert_security_headers;
use crate::pages::templates::SLOW_GAMES;
use crate::{DataBaseRo, WebData};

#[derive(serde_derive::Serialize)]
struct GamesData {
    games: Vec<GameData>,
}

#[derive(serde_derive::Serialize)]
struct GameData {
    gameuid: String,
    gameuidenc: String,
    status: Option<String>,
}

pub async fn slow_games(
    data: web::Data<WebData<'_>>,
    data_ro: web::Data<DataBaseRo>,
) -> HttpResponse {
    let dbclient = match data_ro.0.get().await {
        Ok(client) => client,
        Err(e) => {
            log::error!("{}", e);
            return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
        }
    };

    let stmt = match dbclient
        .prepare("select g.game_uid, g.status::text from games.games g order by g.game_uid;")
        .await
    {
        Ok(stmt) => stmt,
        Err(e) => {
            log::error!("{}", e);
            return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
        }
    };

    let rows = match dbclient.query(&stmt, &[]).await {
        Ok(rows) => rows,
        Err(e) => {
            log::error!("{}", e);
            return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
        }
    };

    let mut games = Vec::with_capacity(rows.len());

    for row in rows {
        let gameuid = row.get::<_, &str>(0);
        let status = row.get::<_, Option<&str>>(1);
        games.push(GameData {
            gameuid: gameuid.to_string(),
            gameuidenc: pct_str::PctString::encode(gameuid.chars(), pct_str::URIReserved)
                .into_string(),
            status: status.map(str::to_string),
        });
    }

    let body = match data.handlebars.render(SLOW_GAMES, &GamesData { games }) {
        Ok(b) => b,
        Err(e) => {
            log::error!("Render slow games error: {}", e);
            return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
        }
    };
    insert_security_headers(HttpResponse::Ok()).body(body)
}