import * as schema from "~/database/schema";
import { eq } from "drizzle-orm";
import { logger } from "~/lib/logger";

import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
import type { Server as SocketIOServer } from "socket.io";

type Db = PostgresJsDatabase<typeof schema>;

export interface StartDraftOptions {
  seasonId: string;
  actorUserId: string;
  actorDisplayName: string;
  db: Db;
  io: SocketIOServer;
}

export interface StartDraftResult {
  success: boolean;
  error?: string;
}

/**
 * Core draft-start logic shared by the commissioner HTTP route and the
 * auto-start timer. Accepts `db` directly (not via AsyncLocalStorage) so it
 * works both inside React Router request context and in the server timer loop.
 */
export async function startDraft(options: StartDraftOptions): Promise<StartDraftResult> {
  const { seasonId, actorUserId, actorDisplayName, db, io } = options;

  const season = await db.query.seasons.findFirst({
    where: eq(schema.seasons.id, seasonId),
  });

  if (!season) {
    return { success: false, error: "Season not found" };
  }

  // Idempotency guard — status may have changed between the outer check and here
  if (season.status !== "pre_draft") {
    return { success: false, error: "Draft already started or completed" };
  }

  const draftSlots = await db.query.draftSlots.findMany({
    where: eq(schema.draftSlots.seasonId, seasonId),
  });

  if (draftSlots.length === 0) {
    return { success: false, error: "No draft slots found for this season" };
  }

  await db
    .update(schema.seasons)
    .set({
      status: "draft",
      currentPickNumber: 1,
      draftStartedAt: new Date(),
    })
    .where(eq(schema.seasons.id, seasonId));

  // Standard mode: each pick gets exactly the increment time.
  // Chess clock mode: each team starts with the full initial bank.
  const initialTime =
    season.draftTimerMode === "standard"
      ? season.draftIncrementTime || 30
      : season.draftInitialTime || 120;

  await db.delete(schema.draftTimers).where(eq(schema.draftTimers.seasonId, seasonId));

  await db.insert(schema.draftTimers).values(
    draftSlots.map((slot) => ({
      seasonId,
      teamId: slot.teamId,
      timeRemaining: initialTime,
    }))
  );

  await db.insert(schema.commissionerAuditLog).values({
    seasonId,
    leagueId: season.leagueId,
    actorUserId,
    actorDisplayName,
    action: "draft_started",
    affectedTeamIds: [],
    details: { pickNumber: 1, autoStarted: actorUserId === "system" },
  });

  try {
    io.to(`draft-${seasonId}`).emit("draft-started", {
      seasonId,
      currentPickNumber: 1,
    });
  } catch (err) {
    // Socket emit failure is non-fatal; DB state is already committed
    logger.error("[startDraft] Socket emit failed:", err);
  }

  return { success: true };
}
