import { auth } from "~/lib/auth.server";
import { addDays, subDays } from "date-fns";
import { ArrowLeft } from "lucide-react";
import { Link } from "react-router";

import type { Route } from "./+types/$leagueId.upcoming-events";
import {
  findLeagueById,
  isCommissioner,
  isUserLeagueMember,
} from "~/models";
import { findCurrentSeasonWithSports } from "~/models/season";
import { findTeamByOwnerAndSeason } from "~/models/team";
import { getDraftedParticipantsBySportsSeason } from "~/models/draft-pick";
import { getUpcomingEventsForDraftedParticipants } from "~/models/scoring-event";
import type { CalendarPanelEvent } from "~/components/sport-season/UpcomingCalendarPanel";
import { UpcomingCalendarPanel } from "~/components/sport-season/UpcomingCalendarPanel";
import { toEventSortKey } from "~/lib/date-utils";

export function meta({ data }: Route.MetaArgs) {
  const leagueName = data?.leagueName ?? "League";
  return [{ title: `${leagueName} — Upcoming Events — Brackt` }];
}

export async function loader(args: Route.LoaderArgs) {
  const session = await auth.api.getSession({ headers: args.request.headers });
  const userId = session?.user.id ?? null;
  const { leagueId } = args.params;

  const league = await findLeagueById(leagueId);
  if (!league) {
    throw new Response("League not found", { status: 404 });
  }

  if (!userId) {
    throw new Response("You must be logged in to view this league", { status: 401 });
  }

  const [isUserCommissioner, isUserMember] = await Promise.all([
    isCommissioner(leagueId, userId),
    isUserLeagueMember(leagueId, userId),
  ]);

  if (!isUserCommissioner && !isUserMember) {
    throw new Response("You do not have access to this league", { status: 403 });
  }

  const seasonWithSports = await findCurrentSeasonWithSports(leagueId);

  const today = new Date();
  const dateFromStr = subDays(today, 1).toISOString().split("T")[0];
  const dateToStr = addDays(today, 60).toISOString().split("T")[0];

  const calendarEvents: CalendarPanelEvent[] = [];

  if (seasonWithSports?.seasonSports && seasonWithSports.id) {
    const myTeam = await findTeamByOwnerAndSeason(userId, seasonWithSports.id);

    if (myTeam) {
      const participantsBySportsSeason = await getDraftedParticipantsBySportsSeason(
        myTeam.id,
        seasonWithSports.id
      );

      const perSeasonEvents = await Promise.all(
        seasonWithSports.seasonSports.map(async ({ sportsSeason: ss }) => {
          const draftedParticipants = participantsBySportsSeason.get(ss.id) ?? [];
          if (draftedParticipants.length === 0) return [];

          const events = await getUpcomingEventsForDraftedParticipants(
            ss.id,
            ss.scoringPattern ?? "",
            draftedParticipants,
            dateFromStr,
            dateToStr
          );

          return events.map((event) => ({
            ...event,
            sportName: ss.sport.name,
            sportSeasonName: ss.name,
            sportsSeasonPageUrl: `/leagues/${leagueId}/sports-seasons/${ss.id}`,
          }));
        })
      );

      calendarEvents.push(...perSeasonEvents.flat());
    }
  }

  const upcomingCalendarEvents = calendarEvents.toSorted((a, b) =>
    toEventSortKey(a).localeCompare(toEventSortKey(b))
  );

  return {
    leagueName: league.name,
    leagueId,
    upcomingCalendarEvents,
  };
}

export default function LeagueUpcomingEventsPage({ loaderData }: Route.ComponentProps) {
  const { leagueName, leagueId, upcomingCalendarEvents } = loaderData;

  return (
    <div className="container mx-auto py-8 px-4 max-w-2xl">
      <div className="mb-6">
        <Link
          to={`/leagues/${leagueId}`}
          className="flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground transition-colors mb-4"
        >
          <ArrowLeft className="h-3.5 w-3.5" />
          {leagueName}
        </Link>
        <h1 className="text-3xl font-bold">Upcoming Events</h1>
        <p className="text-muted-foreground mt-1">Next 60 days · {leagueName}</p>
      </div>

      <UpcomingCalendarPanel
        events={upcomingCalendarEvents}
        showLeague={false}
        emptyMessage="No upcoming events in the next 60 days for this league."
      />
    </div>
  );
}
