import { getAuth } from "@clerk/react-router/server"; import { database } from "~/database/context"; import * as schema from "~/database/schema"; import { eq, and, asc } from "drizzle-orm"; import { getSocketIO } from "~/server/socket"; import { isUserAdminByClerkId } from "~/models/user"; import { getTeamForPick } from "~/lib/draft-order"; import { logger } from "~/lib/logger"; import type { ActionFunctionArgs } from "react-router"; export async function action(args: ActionFunctionArgs) { const { request } = args; const { userId } = await getAuth(args); if (!userId) { return Response.json({ error: "Unauthorized" }, { status: 401 }); } const formData = await request.formData(); const seasonId = formData.get("seasonId") as string; const teamId = formData.get("teamId") as string; const isEnabled = formData.get("isEnabled") === "true"; const mode = formData.get("mode") as "next_pick" | "while_on"; const queueOnly = formData.get("queueOnly") === "true"; if (!seasonId || !teamId || !mode) { return Response.json({ error: "Missing required fields" }, { status: 400 }); } const db = database(); // Fetch team and season in parallel const [team, season] = await Promise.all([ db.query.teams.findFirst({ where: eq(schema.teams.id, teamId) }), db.query.seasons.findFirst({ where: eq(schema.seasons.id, seasonId) }), ]); if (!team || !season) { return Response.json({ error: "Team or season not found" }, { status: 404 }); } const isOwner = team.ownerId === userId; let isActingAsCommissioner = false; if (!isOwner) { const [commissioner, userIsAdmin] = await Promise.all([ db.query.commissioners.findFirst({ where: and( eq(schema.commissioners.leagueId, season.leagueId), eq(schema.commissioners.userId, userId) ), }), isUserAdminByClerkId(userId), ]); if (!commissioner && !userIsAdmin) { return Response.json({ error: "Unauthorized" }, { status: 403 }); } isActingAsCommissioner = true; } const resolvedSource: "commissioner" | "user" = isActingAsCommissioner ? "commissioner" : "user"; // Check if autodraft settings exist const existingSettings = await db.query.autodraftSettings.findFirst({ where: and( eq(schema.autodraftSettings.seasonId, seasonId), eq(schema.autodraftSettings.teamId, teamId) ), }); let settings; if (existingSettings) { // Update existing settings [settings] = await db .update(schema.autodraftSettings) .set({ isEnabled, mode, queueOnly, updatedAt: new Date(), }) .where(eq(schema.autodraftSettings.id, existingSettings.id)) .returning(); } else { // Create new settings [settings] = await db .insert(schema.autodraftSettings) .values({ seasonId, teamId, isEnabled, mode, queueOnly, }) .returning(); } // Emit socket event to notify all clients in the draft room const io = getSocketIO(); io.to(`draft-${seasonId}`).emit("autodraft-updated", { teamId, isEnabled, mode, queueOnly, source: resolvedSource, }); // If commissioner enables autodraft for the team currently on the clock, fire immediately if (isEnabled && isActingAsCommissioner) { import("~/models/draft-utils").then(async ({ executeAutoPick }) => { const freshSeason = await db.query.seasons.findFirst({ where: eq(schema.seasons.id, seasonId), }); if (!freshSeason || freshSeason.status !== "draft") return; const currentPickNumber = freshSeason.currentPickNumber ?? 1; const draftSlots = await db.query.draftSlots.findMany({ where: eq(schema.draftSlots.seasonId, seasonId), orderBy: asc(schema.draftSlots.draftOrder), }); const currentSlot = getTeamForPick(currentPickNumber, draftSlots); if (!currentSlot || currentSlot.teamId !== teamId) return; // Team is on the clock — trigger autopick await executeAutoPick({ seasonId, teamId, pickNumber: currentPickNumber, triggeredBy: "commissioner", db, }); }).catch((err) => { logger.error("[AutodraftUpdate] Mid-turn autopick failed:", err); }); } return Response.json({ success: true, settings }); }