import { eq, and, inArray } from "drizzle-orm"; import { database } from "~/database/context"; import * as schema from "~/database/schema"; export type TournamentGroup = typeof schema.tournamentGroups.$inferSelect; export type TournamentGroupMember = typeof schema.tournamentGroupMembers.$inferSelect; /** * Create empty tournament groups for a scoring event */ export async function createGroupsForEvent( eventId: string, groupLabels: string[] ): Promise { const db = database(); const groups = await db .insert(schema.tournamentGroups) .values( groupLabels.map((label) => ({ scoringEventId: eventId, groupName: label, })) ) .returning(); return groups; } /** * Add participants to a tournament group */ export async function addMembersToGroup( groupId: string, participantIds: string[] ): Promise { const db = database(); const members = await db .insert(schema.tournamentGroupMembers) .values( participantIds.map((participantId) => ({ tournamentGroupId: groupId, participantId, })) ) .returning(); return members; } /** * Find all tournament groups for a scoring event with members and participant data */ export async function findGroupsByEventId(eventId: string) { const db = database(); return await db.query.tournamentGroups.findMany({ where: eq(schema.tournamentGroups.scoringEventId, eventId), orderBy: (groups, { asc }) => [asc(groups.groupName)], with: { members: { with: { participant: true, }, orderBy: (members, { asc }) => [asc(members.createdAt)], }, }, }); } /** * Toggle the eliminated status of a group member */ export async function toggleMemberEliminated( memberId: string ): Promise { const db = database(); // Get current state const member = await db.query.tournamentGroupMembers.findFirst({ where: eq(schema.tournamentGroupMembers.id, memberId), }); if (!member) { throw new Error("Tournament group member not found"); } const [updated] = await db .update(schema.tournamentGroupMembers) .set({ eliminated: !member.eliminated, updatedAt: new Date(), }) .where(eq(schema.tournamentGroupMembers.id, memberId)) .returning(); return updated; } /** * Get participant IDs of non-eliminated group members (advancing teams) */ export async function getAdvancingParticipantIds( eventId: string ): Promise { const db = database(); const groups = await db.query.tournamentGroups.findMany({ where: eq(schema.tournamentGroups.scoringEventId, eventId), with: { members: { where: eq(schema.tournamentGroupMembers.eliminated, false), }, }, }); return groups.flatMap((g) => g.members.map((m) => m.participantId)); } /** * Get participant IDs of eliminated group members */ export async function getEliminatedParticipantIds( eventId: string ): Promise { const db = database(); const groups = await db.query.tournamentGroups.findMany({ where: eq(schema.tournamentGroups.scoringEventId, eventId), with: { members: { where: eq(schema.tournamentGroupMembers.eliminated, true), }, }, }); return groups.flatMap((g) => g.members.map((m) => m.participantId)); } /** * Delete all tournament groups for a scoring event (for regeneration) */ export async function deleteGroupsByEventId(eventId: string): Promise { const db = database(); // Members cascade-delete when groups are deleted await db .delete(schema.tournamentGroups) .where(eq(schema.tournamentGroups.scoringEventId, eventId)); }