use crate::{ app::AppState, error::AppResult, models::club::Club, services::{checkin as checkin_svc, club as club_svc, profile as profile_svc, statistics as stats_svc}, }; use axum::{extract::State, Json}; use serde::Deserialize; use serde_json::{json, Value}; pub async fn get_club(State(state): State) -> AppResult> { let profile = profile_svc::get_active_profile(&state.pool).await?; let club = club_svc::get_club_by_profile(&state.pool, &profile.id).await?; Ok(Json(club)) } #[derive(Deserialize)] pub struct UpdateClubRequest { pub name: Option, pub manager_name: Option, } pub async fn put_club( State(state): State, Json(req): Json, ) -> AppResult> { let profile = profile_svc::get_active_profile(&state.pool).await?; let club = club_svc::get_club_by_profile(&state.pool, &profile.id).await?; let updated = club_svc::update_club( &state.pool, &club.id, req.name.as_deref(), req.manager_name.as_deref(), ) .await?; Ok(Json(json!({ "club": updated }))) } pub async fn get_checkin_status(State(state): State) -> AppResult> { let profile = profile_svc::get_active_profile(&state.pool).await?; let status = checkin_svc::get_status(&state.pool, &profile.id).await?; Ok(Json(json!({ "available": status.available, "streak_day": status.streak_day, "next_reward_coins": status.next_reward_coins, "next_reward_pack": status.next_reward_pack, "last_checked_in": status.last_checked_in, }))) } pub async fn post_checkin(State(state): State) -> AppResult> { let profile = profile_svc::get_active_profile(&state.pool).await?; let club = club_svc::get_club_by_profile(&state.pool, &profile.id).await?; let r = checkin_svc::claim(&state.pool, &profile.id, &club.id).await?; Ok(Json(json!({ "coins_awarded": r.coins_awarded, "pack_awarded": r.pack_awarded, "new_streak": r.new_streak, "already_claimed": r.already_claimed, }))) } pub async fn get_milestones(State(state): State) -> AppResult> { let profile = profile_svc::get_active_profile(&state.pool).await?; let club = club_svc::get_club_by_profile(&state.pool, &profile.id).await?; let stats = stats_svc::get_or_create(&state.pool, &profile.id).await?; let seasons_completed: i64 = sqlx::query_scalar( "SELECT COUNT(*) FROM season_history WHERE profile_id = ?", ) .bind(&profile.id) .fetch_one(&state.pool) .await .unwrap_or(0); let highest_division: i64 = sqlx::query_scalar( "SELECT COALESCE(MIN(new_division), 10) FROM season_history WHERE profile_id = ?", ) .bind(&profile.id) .fetch_one(&state.pool) .await .unwrap_or(10); let cards_owned: i64 = sqlx::query_scalar( "SELECT COUNT(*) FROM owned_cards WHERE club_id = ?", ) .bind(&club.id) .fetch_one(&state.pool) .await .unwrap_or(0); let sbcs_completed: i64 = sqlx::query_scalar( "SELECT COUNT(*) FROM sbc_submissions WHERE club_id = ? AND passed = 1", ) .bind(&club.id) .fetch_one(&state.pool) .await .unwrap_or(0); let total_checkins: i64 = sqlx::query_scalar( "SELECT COUNT(*) FROM daily_checkins WHERE profile_id = ?", ) .bind(&profile.id) .fetch_one(&state.pool) .await .unwrap_or(0); Ok(Json(json!({ "total_wins": stats.matches_won, "total_draws": stats.matches_drawn, "total_losses": stats.matches_lost, "total_matches": stats.matches_played, "total_goals_scored": stats.goals_scored, "total_goals_conceded": stats.goals_conceded, "best_win_streak": stats.best_win_streak, "total_packs_opened": stats.packs_opened, "seasons_completed": seasons_completed, "highest_division_reached": highest_division, "cards_owned": cards_owned, "sbcs_completed": sbcs_completed, "total_checkins": total_checkins, "club_level": club.level, }))) }