use crate::extractors::GameId; use axum::{ extract::{Query, State}, Json, }; use serde::Deserialize; use serde_json::{json, Value}; use crate::{ app::AppState, error::AppResult, models::match_result::Match, services::{profile as profile_svc, statistics as stats_svc}, }; pub async fn get_statistics(State(state): State, game: GameId) -> AppResult> { let profile = profile_svc::get_active_profile(&state.pool, game.as_str()).await?; let stats = stats_svc::get_or_create(&state.pool, &profile.id).await?; let pos_goals = stats_svc::get_position_goals(&state.pool, &profile.id).await?; let pos_map: serde_json::Map = pos_goals .into_iter() .map(|(pos, goals)| (pos, Value::Number(goals.into()))) .collect(); let mut val = serde_json::to_value(&stats)?; if let Some(obj) = val.as_object_mut() { obj.insert("position_goals".into(), Value::Object(pos_map)); } Ok(Json(val)) } #[derive(Deserialize)] pub struct HistoryQuery { pub limit: Option, } pub async fn get_statistics_history( State(state): State, game: GameId, Query(query): Query, ) -> AppResult> { let profile = profile_svc::get_active_profile(&state.pool, game.as_str()).await?; let limit = query.limit.unwrap_or(20).clamp(1, 100); let matches = sqlx::query_as::<_, Match>( "SELECT id, profile_id, squad_id, opponent_name, goals_for, goals_against, outcome, coins_awarded, xp_awarded, mode, played_at FROM matches WHERE profile_id = ? ORDER BY played_at DESC LIMIT ?", ) .bind(&profile.id) .bind(limit) .fetch_all(&state.pool) .await?; let total = matches.len(); let wins = matches.iter().filter(|m| m.outcome == "win").count(); let draws = matches.iter().filter(|m| m.outcome == "draw").count(); let losses = matches.iter().filter(|m| m.outcome == "loss").count(); let goals_for: i64 = matches.iter().map(|m| m.goals_for).sum(); let goals_against: i64 = matches.iter().map(|m| m.goals_against).sum(); let win_rate = if total > 0 { wins as f64 / total as f64 } else { 0.0 }; let avg_goals = if total > 0 { goals_for as f64 / total as f64 } else { 0.0 }; Ok(Json(json!({ "matches": matches, "summary": { "total": total, "wins": wins, "draws": draws, "losses": losses, "win_rate": (win_rate * 100.0).round() / 100.0, "total_goals_for": goals_for, "total_goals_against": goals_against, "avg_goals_per_game": (avg_goals * 100.0).round() / 100.0, } }))) }