import type { Route } from "./+types/admin.sports-seasons.$id.events";
import { redirect } from "react-router";
import { logger } from "~/lib/logger";
import { findSportsSeasonById } from "~/models/sports-season";
import {
  getScoringEventsForSportsSeason,
  createScoringEvent,
  deleteScoringEvent,
  bulkCreateScoringEvents,
  type CreateScoringEventData,
} from "~/models/scoring-event";
import { getQPStandings } from "~/models/qualifying-points";
import { finalizeQualifyingPoints } from "~/models/scoring-calculator";
import { maybeResolveCompletedBracktForSportsSeason } from "~/services/brackt.server";
import { upsertTournament, findTournamentsBySport, getTournamentById } from "~/models/tournament";
import { extractTournamentIdentity } from "~/lib/tournament-identity";


export async function loader({ params }: Route.LoaderArgs) {
  const sportsSeason = await findSportsSeasonById(params.id);

  if (!sportsSeason) {
    throw new Response("Sports season not found", { status: 404 });
  }

  const events = await getScoringEventsForSportsSeason(params.id);

  // For qualifying sports seasons, get QP standings
  let qpStandings = null;
  const scoringRules = null;
  if (sportsSeason.scoringPattern === "qualifying_points") {
    qpStandings = await getQPStandings(params.id);
  }

  // Tournaments for this sport that don't already have a scoring event in this season.
  // Only relevant for qualifying_points seasons — skip the query for all others.
  const allTournamentsForSport =
    sportsSeason.scoringPattern === "qualifying_points"
      ? await findTournamentsBySport(sportsSeason.sportId)
      : [];
  const linkedTournamentIds = new Set(
    events.map((e) => e.tournamentId).filter((id): id is string => id !== null)
  );
  const availableTournaments = allTournamentsForSport.filter((t) => !linkedTournamentIds.has(t.id));

  return {
    sportsSeason: sportsSeason as typeof sportsSeason & {
      sport: { id: string; name: string; type: string; slug: string };
    },
    events,
    qpStandings,
    scoringRules,
    availableTournaments,
  };
}

export async function action({ request, params }: Route.ActionArgs) {
  const formData = await request.formData();
  const intent = formData.get("intent");

  if (intent === "add-from-tournament") {
    const tournamentId = formData.get("tournamentId");
    if (typeof tournamentId !== "string" || !tournamentId) {
      return { error: "Tournament ID is required" };
    }
    try {
      const tournament = await getTournamentById(tournamentId);
      if (!tournament) return { error: "Tournament not found" };
      const eventDate = tournament.startsAt ? new Date(tournament.startsAt) : undefined;
      // This action is only reachable for qualifying_points seasons (the card is
      // conditional in the UI), so major_tournament + isQualifyingEvent=true is always correct.
      const event = await createScoringEvent({
        sportsSeasonId: params.id,
        name: `${tournament.name} ${tournament.year}`,
        eventType: "major_tournament",
        isQualifyingEvent: true,
        tournamentId: tournament.id,
        eventDate,
        eventStartsAt: tournament.startsAt ? new Date(tournament.startsAt) : undefined,
      });
      return redirect(`/admin/sports-seasons/${params.id}/events/${event.id}`);
    } catch (error) {
      logger.error("Error adding scoring event from tournament:", error);
      return { error: "Failed to create scoring event from tournament." };
    }
  }

  if (intent === "finalize-qp") {
    try {
      await finalizeQualifyingPoints(params.id);
      await maybeResolveCompletedBracktForSportsSeason(params.id);
      return { success: "Qualifying points finalized and fantasy placements assigned to top 8!" };
    } catch (error) {
      logger.error("Error finalizing qualifying points:", error);
      return { error: error instanceof Error ? error.message : "Failed to finalize qualifying points" };
    }
  }

  if (intent === "bulk-create") {
    const bulkText = formData.get("bulkEvents");
    const bulkEventType = formData.get("bulkEventType");

    if (typeof bulkText !== "string" || !bulkText.trim()) {
      return { error: "Event list is required" };
    }

    const validTypes = ["playoff_game", "major_tournament", "schedule_event"] as const;
    type ValidEventType = typeof validTypes[number];
    const eventType: ValidEventType =
      validTypes.includes(bulkEventType as ValidEventType)
        ? (bulkEventType as ValidEventType)
        : "playoff_game";

    const sportsSeason = await findSportsSeasonById(params.id);
    if (!sportsSeason) return { error: "Sports season not found" };

    const isQualifyingDefault =
      sportsSeason.scoringPattern === "qualifying_points" &&
      eventType === "major_tournament";

    // Parse lines: "Name, YYYY-MM-DD[, HH:MM]" or tab-separated, or just "Name"
    const lines = bulkText
      .split("\n")
      .map((l) => l.trim())
      .filter(Boolean);

    const parsedEvents = lines.map((line) => {
      const parts = line.split(/[,\t]/).map((p) => p.trim());
      const name = parts[0];
      const dateStr = parts[1];
      const timeStr = parts[2];
      const eventDate =
        dateStr && /^\d{4}-\d{2}-\d{2}$/.test(dateStr)
          ? new Date(dateStr)
          : undefined;
      const eventStartsAt =
        eventDate && dateStr && timeStr && /^\d{2}:\d{2}$/.test(timeStr)
          ? new Date(`${dateStr}T${timeStr}:00.000Z`)
          : undefined;
      return { name, eventDate, eventStartsAt, eventType, isQualifyingEvent: isQualifyingDefault };
    });

    const validEvents = parsedEvents.filter((e) => e.name);
    if (validEvents.length === 0) {
      return { error: "No valid events found. Use format: Event Name, YYYY-MM-DD" };
    }

    // Auto-provision canonical tournaments for qualifying events (check constraint).
    try {
      for (const ev of validEvents) {
        if (!ev.isQualifyingEvent) continue;
        const identity = extractTournamentIdentity({
          name: ev.name,
          eventDate: ev.eventDate ? ev.eventDate.toISOString().slice(0, 10) : null,
          eventType: ev.eventType,
        });
        const tournament = await upsertTournament({
          sportId: sportsSeason.sportId,
          name: identity.name,
          year: identity.year,
          startsAt: ev.eventStartsAt ?? null,
        });
        (ev as typeof ev & { tournamentId: string }).tournamentId = tournament.id;
      }
    } catch (err) {
      logger.error("Error linking qualifying events to canonical tournaments:", err);
      return {
        error:
          "Could not determine tournament identity for one or more qualifying events. Include a 4-digit year or date for each.",
      };
    }

    try {
      await bulkCreateScoringEvents(params.id, validEvents);
      return { success: `Created ${validEvents.length} event${validEvents.length !== 1 ? "s" : ""} successfully` };
    } catch (error) {
      logger.error("Error bulk creating events:", error);
      return { error: "Failed to create events. Please try again." };
    }
  }

  if (intent === "delete-event") {
    const eventId = formData.get("eventId");

    if (typeof eventId !== "string" || !eventId) {
      return { error: "Event ID is required" };
    }

    try {
      await deleteScoringEvent(eventId);
      return { success: "Event deleted successfully" };
    } catch (error) {
      logger.error("Error deleting event:", error);
      return { error: "Failed to delete event" };
    }
  }

  const name = formData.get("name");
  const eventType = formData.get("eventType");
  const eventStartsAtRaw = formData.get("eventStartsAt");

  // Validation
  if (typeof name !== "string" || !name.trim()) {
    return { error: "Event name is required" };
  }

  if (
    eventType !== "playoff_game" &&
    eventType !== "major_tournament" &&
    eventType !== "schedule_event"
  ) {
    return { error: "Invalid event type" };
  }

  // Get the sports season to check if this should be a qualifying event
  const sportsSeason = await findSportsSeasonById(params.id);
  if (!sportsSeason) {
    return { error: "Sports season not found" };
  }

  // Automatically mark major tournaments as qualifying events for qualifying_points sports seasons
  const isQualifyingEvent =
    sportsSeason.scoringPattern === "qualifying_points" &&
    eventType === "major_tournament";

  // eventStartsAt is a UTC ISO string produced by localDateTimeToUtcIso on the client
  const eventStartsAt =
    typeof eventStartsAtRaw === "string" && eventStartsAtRaw
      ? new Date(eventStartsAtRaw)
      : undefined;

  // Derive eventDate from eventStartsAt (UTC date portion)
  const eventDate = eventStartsAt ? new Date(eventStartsAt.toISOString().split("T")[0]) : undefined;

  const eventData: CreateScoringEventData = {
    sportsSeasonId: params.id,
    name: name.trim(),
    eventType: eventType as "playoff_game" | "major_tournament" | "schedule_event",
    eventDate,
    eventStartsAt,
    isQualifyingEvent,
  };

  // Qualifying events require a canonical tournament_id (check constraint).
  // Auto-provision one by extracting (name, year) from the event name/date.
  if (isQualifyingEvent) {
    try {
      const identity = extractTournamentIdentity({
        name: eventData.name,
        eventDate: eventDate ? eventDate.toISOString().slice(0, 10) : null,
        eventType,
      });
      const tournament = await upsertTournament({
        sportId: sportsSeason.sportId,
        name: identity.name,
        year: identity.year,
        startsAt: eventStartsAt ?? null,
      });
      eventData.tournamentId = tournament.id;
    } catch (err) {
      logger.error("Error linking qualifying event to canonical tournament:", err);
      return {
        error:
          "Could not determine tournament identity. Include a 4-digit year in the event name, or set a date.",
      };
    }
  }

  try {
    const event = await createScoringEvent(eventData);
    return redirect(`/admin/sports-seasons/${params.id}/events/${event.id}`);
  } catch (error) {
    logger.error("Error creating scoring event:", error);
    return { error: "Failed to create scoring event. Please try again." };
  }
}
