import { MAX_TEAM_SIZE } from '@/lib/game/crew' // The crew-team half of a queueing-action body (leadCrewId + helperCrewIds) plus the route-layer // team rules: one task team, distinct members, the size cap. queueTask (lib) deliberately does // NOT validate teams, so this shared parse is the single place the team 400s live — extracted // verbatim from the 5a jump/explore crew-parse blocks so the six queueing routes can't drift. // Returns a 400-shaped error object instead of throwing, so the caller maps it to a response. export type CrewTeam = | { leadCrewId: number; helperCrewIds: number[] } | { error: string; status: number } export function parseCrewTeam(body: unknown): CrewTeam { const leadCrewId = (body as { leadCrewId?: unknown }).leadCrewId if (typeof leadCrewId !== 'number' || !Number.isInteger(leadCrewId)) { return { error: 'leadCrewId must be an integer', status: 400 } } let helperCrewIds: number[] = [] const rawHelpers = (body as { helperCrewIds?: unknown }).helperCrewIds if (rawHelpers !== undefined) { if (!Array.isArray(rawHelpers) || !rawHelpers.every((h) => typeof h === 'number' && Number.isInteger(h))) { return { error: 'helperCrewIds must be an array of integers', status: 400 } } helperCrewIds = rawHelpers } // Team rules (route layer, not queueTask's): one task team, distinct members, size cap. const team = [leadCrewId, ...helperCrewIds] if (new Set(team).size !== team.length) { return { error: 'crew members must be unique', status: 400 } } if (team.length > MAX_TEAM_SIZE) { return { error: `a task team holds at most ${MAX_TEAM_SIZE} crew members`, status: 400 } } return { leadCrewId, helperCrewIds } }