import { data, type ActionFunctionArgs } from "react-router"; import { getAuth } from "@clerk/react-router/server"; import { findSeasonById, updateSeason, updateSeasonStatus, findTeamsBySeasonId, isCommissioner, createDraftPick, initializeDraftTimers, updateTeamTimer, getSeasonTimers, autoPickForTeam, calculatePickInfo, removeFromQueue, getTeamQueue, } from "~/models"; import { getSocketIO } from "../../../server/socket.js"; export async function action(args: ActionFunctionArgs) { const { userId } = await getAuth(args); if (!userId) { return data({ error: "Unauthorized" }, { status: 401 }); } const { request } = args; const formData = await request.formData(); const actionType = formData.get("action"); const seasonId = formData.get("seasonId"); if (!seasonId || typeof seasonId !== "string") { return data({ error: "Season ID is required" }, { status: 400 }); } // Get season const season = await findSeasonById(seasonId); if (!season) { return data({ error: "Season not found" }, { status: 404 }); } // Verify user is commissioner const isUserCommissioner = await isCommissioner(season.leagueId, userId); if (!isUserCommissioner) { return data({ error: "Only commissioners can perform this action" }, { status: 403 }); } try { const io = getSocketIO(); switch (actionType) { case "start-draft": { // Check if draft already started if (season.draftStartedAt) { return data({ error: "Draft has already started" }, { status: 400 }); } // Get teams const teams = await findTeamsBySeasonId(seasonId); // Initialize timers await initializeDraftTimers(seasonId, teams, season.draftInitialTime || 120); // Update season await updateSeason(seasonId, { draftStartedAt: new Date(), currentPickNumber: 1, draftPaused: false, }); await updateSeasonStatus(seasonId, "draft"); // Get updated timers const timers = await getSeasonTimers(seasonId); // Broadcast to all clients io.to(`draft-${seasonId}`).emit("draft-started", { seasonId, startedAt: new Date(), timers, }); return data({ success: true }); } case "pause-draft": { const pause = formData.get("pause") === "true"; // Check if draft has started if (!season.draftStartedAt) { return data({ error: "Draft has not started yet" }, { status: 400 }); } // Update season await updateSeason(seasonId, { draftPaused: pause }); // Broadcast to all clients io.to(`draft-${seasonId}`).emit("draft-paused", { seasonId, isPaused: pause, }); return data({ success: true }); } case "force-pick": { const teamId = formData.get("teamId"); if (!teamId || typeof teamId !== "string") { return data({ error: "Team ID is required" }, { status: 400 }); } // Check if draft has started if (!season.draftStartedAt) { return data({ error: "Draft has not started" }, { status: 400 }); } // Check if draft is complete const teams = await findTeamsBySeasonId(seasonId); const totalPicks = season.draftRounds * teams.length; const currentPickNumber = season.currentPickNumber || 1; if (currentPickNumber > totalPicks) { return data({ error: "Draft is already complete" }, { status: 400 }); } // Auto-pick for the team const participantId = await autoPickForTeam(seasonId, teamId); if (!participantId) { return data({ error: "No available participants to pick" }, { status: 400 }); } // Calculate pick info const { round, pickInRound } = calculatePickInfo(currentPickNumber, teams.length); // Create the draft pick const pick = await createDraftPick({ seasonId, teamId, participantId, pickNumber: currentPickNumber, round, pickInRound, pickedByUserId: userId, pickedByType: "commissioner", timeUsed: 0, }); // Remove from queue if it was queued const queue = await getTeamQueue(teamId); const queueItem = queue.find((item: any) => item.participantId === participantId); if (queueItem) { await removeFromQueue(queueItem.id); } // Update season to next pick const nextPickNumber = currentPickNumber + 1; await updateSeason(seasonId, { currentPickNumber: nextPickNumber }); // Add increment time to current team's timer if (season.draftIncrementTime) { const timers = await getSeasonTimers(seasonId); const currentTimer = timers.find((t: any) => t.teamId === teamId); if (currentTimer) { const newTime = currentTimer.timeRemaining + season.draftIncrementTime; await updateTeamTimer(teamId, newTime); } } // Check if draft is complete if (nextPickNumber > totalPicks) { await updateSeasonStatus(seasonId, "active"); io.to(`draft-${seasonId}`).emit("draft-completed", { seasonId, }); } // Broadcast pick to all clients in the room io.to(`draft-${seasonId}`).emit("pick-made", { pick, nextPickNumber, isDraftComplete: nextPickNumber > totalPicks, }); // Emit queue update to team owner const updatedQueue = await getTeamQueue(teamId); io.to(`draft-${seasonId}`).emit("queue-updated", { teamId, queue: updatedQueue, }); return data({ success: true, pick }); } default: return data({ error: "Invalid action" }, { status: 400 }); } } catch (error) { console.error("Commissioner action error:", error); return data({ error: error instanceof Error ? error.message : "Failed to perform action" }, { status: 500 }); } }