================================================================================
                        CROCK HUNT — API DOCUMENTATION
================================================================================
Base URL : https://testing.reasonistic.com/crock-hunt
Auth     : Bearer token in Authorization header (except public endpoints)
Format   : application/json

KEY SIMPLIFICATIONS
  - No numeric IDs in any request. Use room_code everywhere.
  - Guess a player by their player_order (1, 2, 3 …) not a database ID.
  - After joining or creating a game the room_code is all you need to keep.
================================================================================


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 1. REGISTER
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/auth/register
Auth        : Not required
Source      : app/Controllers/Api/Auth.php  (line 25)

Description :
  Creates a new user account. Returns a Bearer token valid for 30 days along
  with the new user's id and name.

Request Body:
  {
    "name"     : "John",            (required, 2–100 chars)
    "email"    : "john@email.com",  (required, unique)
    "password" : "secret123"        (required, min 6 chars)
  }

Response (201):
  {
    "status" : true,
    "token"  : "<64-char hex token>",
    "user"   : { "id": 1, "name": "John" }
  }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/auth/register \
    -H "Content-Type: application/json" \
    -d '{"name":"John","email":"john@email.com","password":"secret123"}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 2. LOGIN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/auth/login
Auth        : Not required
Source      : app/Controllers/Api/Auth.php  (line 51)

Description :
  Authenticates an existing user. Returns a fresh Bearer token along with the
  user's id, name, and email.

Request Body:
  {
    "email"    : "john@email.com",  (required)
    "password" : "secret123"        (required)
  }

Response (200):
  {
    "status" : true,
    "token"  : "<64-char hex token>",
    "user"   : { "id": 1, "name": "John", "email": "john@email.com" }
  }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/auth/login \
    -H "Content-Type: application/json" \
    -d '{"email":"john@email.com","password":"secret123"}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 3. LOGOUT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/auth/logout
Auth        : Required
Source      : app/Controllers/Api/Auth.php  (line 75)

Description :
  Invalidates the current Bearer token. The user must log in again to get
  a new token.

Request Body: (none)

Response (200):
  { "status": true, "message": "Logged out" }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/auth/logout \
    -H "Authorization: Bearer YOUR_TOKEN"


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 4. ME (CURRENT USER PROFILE)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : GET
URL         : /api/auth/me
Auth        : Required
Source      : app/Controllers/Api/Auth.php  (line 83)

Description :
  Returns the profile of the currently authenticated user.

Request Body: (none)

Response (200):
  {
    "status" : true,
    "user"   : { "id": 1, "name": "John", "email": "john@email.com" }
  }

CURL:
  curl https://testing.reasonistic.com/crock-hunt/api/auth/me \
    -H "Authorization: Bearer YOUR_TOKEN"


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 5. LEADERBOARD (PUBLIC SCORES)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : GET
URL         : /api/scores
Auth        : Not required
Source      : app/Controllers/Api/Scores.php  (line 14)

Description :
  Returns the top 20 all-time high scores. No token needed.

Request Body: (none)

Response (200):
  { "status": true, "data": [ ...top 20 score records... ] }

CURL:
  curl https://testing.reasonistic.com/crock-hunt/api/scores


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 6. CREATE GAME
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games
Auth        : Required
Source      : app/Controllers/Api/Games.php  (line 29)

Description :
  Creates a new game room. The caller becomes host and is added as player #1.
  Returns a room_code — this is the only value clients need to keep.

Request Body:
  {
    "display_name" : "John",       (required, 2–100 chars — in-game name)
    "game_mode"    : "classic",    (required, "classic" or "freestyle")
    "total_rounds" : 5,            (required, integer 1–15)
    "color_argb"   : 4294901760    (required, integer — player avatar color)
  }

Response (201):
  {
    "status"    : true,
    "room_code" : "ABC123"
  }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"display_name":"John","game_mode":"classic","total_rounds":5,"color_argb":4294901760}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 7. JOIN GAME
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games/join
Auth        : Required
Source      : app/Controllers/Api/Games.php  (line 68)

Description :
  Joins an existing waiting room by room code. Re-joining a room the user is
  already in returns "Rejoined". Maximum 8 players.

Request Body:
  {
    "room_code"    : "ABC123",    (required, 6–8 chars)
    "display_name" : "Jane",      (required, 2–100 chars — in-game name)
    "color_argb"   : 4278190335   (required, integer — player avatar color)
  }

Response (200):
  {
    "status"  : true,
    "message" : "Joined"    (or "Rejoined" if already in room)
  }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games/join \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"room_code":"ABC123","display_name":"Jane","color_argb":4278190335}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 8. GET GAME STATE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : GET
URL         : /api/games/{room_code}
Auth        : Required
Source      : app/Controllers/Api/Games.php  (line 108)

Description :
  Returns the full current state of the game — players, current phase, round,
  and scores. Flutter polls this every 2 seconds to keep all clients in sync.
  Each player only sees their own role; other players' roles are hidden (null).

Request Body: (none)

Response (200):
  {
    "status" : true,
    "data"   : {
      "room_code"         : "ABC123",
      "mode"              : "classic",
      "status"            : "in_progress",
      "current_phase"     : "police_identification",
      "current_round"     : 1,
      "total_rounds"      : 5,
      "is_host"           : true,
      "is_my_turn"        : false,
      "my_role"           : "king",
      "players"           : [
        {
          "display_name"  : "John",
          "player_order"  : 1,
          "color_argb"    : 4294901760,
          "total_score"   : 1000,
          "has_seen_role" : true,
          "current_role"  : "king"    (null for other players)
        },
        ...
      ]
    }
  }

CURL:
  curl https://testing.reasonistic.com/crock-hunt/api/games/ABC123 \
    -H "Authorization: Bearer YOUR_TOKEN"


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 9. START GAME
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games/start
Auth        : Required (host only)
Source      : app/Controllers/Api/Games.php  (line 120)

Description :
  Host-only. Assigns secret roles to all players and moves the game from
  "waiting" to "secret_draw" phase. Non-host callers receive an error.
  Requires at least 3 players.

Request Body:
  {
    "room_code" : "ABC123"   (required)
  }

Response (200):
  { "status": true, "message": "Game started" }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games/start \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"room_code":"ABC123"}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 10. SEEN ROLE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games/seen-role
Auth        : Required
Source      : app/Controllers/Api/Games.php  (line 138)

Description :
  Each player calls this after reading their secret role card. Once every
  player confirms, the game advances automatically to the guessing phase.

Request Body:
  {
    "room_code" : "ABC123"   (required)
  }

Response (200):
  {
    "status"   : true,
    "all_seen" : false    (true once every player has confirmed)
  }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games/seen-role \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"room_code":"ABC123"}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 11. CLASSIC GUESS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games/guess/classic
Auth        : Required (police player only)
Source      : app/Controllers/Api/GamePlay.php  (line 27)

Description :
  Police player accuses a suspect in classic mode. Use player_order from the
  game state (1, 2, 3 …) to identify the suspect — no database ID needed.

Request Body:
  {
    "room_code"    : "ABC123",   (required)
    "player_order" : 3           (required — order number of the accused player)
  }

Response (200):
  {
    "status" : true,
    "data"   : {
      "correct_guess" : true,
      "message"       : "Crook caught!"
    }
  }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games/guess/classic \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"room_code":"ABC123","player_order":3}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 12. FREESTYLE GUESS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games/guess/freestyle
Auth        : Required (current turn player only)
Source      : app/Controllers/Api/GamePlay.php  (line 57)

Description :
  The current turn player accuses a suspect in freestyle mode. Roles cascade
  down a chain — a wrong guess swaps roles between guesser and suspect.
  Use player_order from the game state to identify the suspect.

Request Body:
  {
    "room_code"    : "ABC123",   (required)
    "player_order" : 2           (required — order number of the accused player)
  }

Response (200):
  {
    "status" : true,
    "data"   : {
      "was_correct"  : false,
      "guesser_role" : "king",
      "target_role"  : "queen"
    }
  }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games/guess/freestyle \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"room_code":"ABC123","player_order":2}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 13. ADVANCE — RESULT SCREEN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games/advance/result
Auth        : Required
Source      : app/Controllers/Api/GamePlay.php  (line 87)

Description :
  Moves the game past the freestyle result screen into the resolution or next
  guess phase, depending on whether the round has ended.

Request Body:
  {
    "room_code" : "ABC123"   (required)
  }

Response (200):
  { "status": true }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games/advance/result \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"room_code":"ABC123"}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 14. ADVANCE — RESOLUTION SCREEN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games/advance/resolution
Auth        : Required
Source      : app/Controllers/Api/GamePlay.php  (line 104)

Description :
  Moves the game past the resolution screen (crook revealed) to the scoreboard.

Request Body:
  {
    "room_code" : "ABC123"   (required)
  }

Response (200):
  { "status": true }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games/advance/resolution \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"room_code":"ABC123"}'


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 15. ADVANCE — SCOREBOARD
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method      : POST
URL         : /api/games/advance/scoreboard
Auth        : Required (host only)
Source      : app/Controllers/Api/GamePlay.php  (line 121)

Description :
  Host-only. Moves past the scoreboard. Starts the next round if rounds remain,
  or ends the game and saves final scores if it was the last round.

Request Body:
  {
    "room_code" : "ABC123"   (required)
  }

Response (200):
  {
    "status" : true,
    "data"   : { "next_phase": "secret_draw", "round": 2 }
    // or on final round:
    "data"   : { "next_phase": "game_over" }
  }

CURL:
  curl -X POST https://testing.reasonistic.com/crock-hunt/api/games/advance/scoreboard \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"room_code":"ABC123"}'


================================================================================
 AUTH MIDDLEWARE — HOW IT WORKS
================================================================================
Source : app/Filters/AuthFilter.php

Every protected endpoint checks for:
  Authorization: Bearer <token>

If the token is missing, expired, or invalid:
  HTTP 401  { "status": false, "message": "Unauthorized: ..." }

Tokens are issued on register/login and are valid for 30 days.
Calling /api/auth/logout deletes the token immediately.

================================================================================
 QUICK REFERENCE TABLE
================================================================================

 #  | Auth | Method | Endpoint                          | Body fields
----|------|--------|-----------------------------------|--------------------------
 1  |  No  | POST   | /api/auth/register                | name, email, password
 2  |  No  | POST   | /api/auth/login                   | email, password
 3  | Yes  | POST   | /api/auth/logout                  | —
 4  | Yes  | GET    | /api/auth/me                      | —
 5  |  No  | GET    | /api/scores                       | —
 6  | Yes  | POST   | /api/games                        | display_name, game_mode, total_rounds, color_argb
 7  | Yes  | POST   | /api/games/join                   | room_code, display_name, color_argb
 8  | Yes  | GET    | /api/games/{room_code}            | —
 9  | Yes  | POST   | /api/games/start                  | room_code
 10 | Yes  | POST   | /api/games/seen-role              | room_code
 11 | Yes  | POST   | /api/games/guess/classic          | room_code, player_order
 12 | Yes  | POST   | /api/games/guess/freestyle        | room_code, player_order
 13 | Yes  | POST   | /api/games/advance/result         | room_code
 14 | Yes  | POST   | /api/games/advance/resolution     | room_code
 15 | Yes  | POST   | /api/games/advance/scoreboard     | room_code

================================================================================
 TYPICAL FLOW
================================================================================

  Host device                          Guest device
  ──────────────────────────────────   ──────────────────────────────────────
  POST /api/auth/register              POST /api/auth/register
  POST /api/games  → room_code         POST /api/games/join  (room_code)
  GET  /api/games/{room_code}  ← poll every 2 s →  GET /api/games/{room_code}
  POST /api/games/start
                                       POST /api/games/seen-role
  POST /api/games/seen-role
  POST /api/games/guess/classic        (or freestyle, player_order from state)
  POST /api/games/advance/resolution
  POST /api/games/advance/scoreboard
  (repeat rounds …)

================================================================================
