package handlers import ( "database/sql" "net/http" "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/tas/horchposten/models" ) // PlayerStats handles GET /api/analytics/player/:client_id/ func PlayerStats(db *sql.DB) echo.HandlerFunc { return func(c echo.Context) error { clientID := c.Param("client_id") if _, err := uuid.Parse(clientID); err != nil { return c.JSON(http.StatusBadRequest, echo.Map{"error": "invalid client_id format"}) } // Look up player. var playerID int64 var totalSessions int var firstSeen string err := db.QueryRow( "SELECT id, total_sessions, first_seen FROM players WHERE client_id = ?", clientID, ).Scan(&playerID, &totalSessions, &firstSeen) if err == sql.ErrNoRows { return c.JSON(http.StatusNotFound, echo.Map{"error": "player not found"}) } else if err != nil { return c.JSON(http.StatusInternalServerError, echo.Map{"error": "database error"}) } // Get high score. var highScore *int var hs int err = db.QueryRow( "SELECT score FROM high_scores WHERE player_id = ?", playerID, ).Scan(&hs) if err == nil { highScore = &hs } // Get last 50 sessions. rows, err := db.Query( `SELECT id, score, level_reached, lives_used, duration_seconds, end_reason, started_at, ended_at FROM game_sessions WHERE player_id = ? ORDER BY ended_at DESC LIMIT 50`, playerID, ) if err != nil { return c.JSON(http.StatusInternalServerError, echo.Map{"error": "database error"}) } defer rows.Close() sessions := make([]models.SessionSummary, 0) for rows.Next() { var s models.SessionSummary var startedAt, endedAt string if err := rows.Scan( &s.SessionID, &s.Score, &s.LevelReached, &s.LivesUsed, &s.DurationSeconds, &s.EndReason, &startedAt, &endedAt, ); err != nil { return c.JSON(http.StatusInternalServerError, echo.Map{"error": "scan error"}) } s.StartedAt = parseTime(startedAt) s.EndedAt = parseTime(endedAt) sessions = append(sessions, s) } resp := models.PlayerStatsResponse{ ClientID: clientID, TotalSessions: totalSessions, FirstSeen: parseTime(firstSeen), HighScore: highScore, Sessions: sessions, } return c.JSON(http.StatusOK, resp) } }