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/upcoming-events";
import { findLeaguesWithActiveSeasonsByUserId } from "~/models/league";
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() {
  return [{ title: "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;

  if (!userId) {
    return { isLoggedIn: false as const, upcomingCalendarEvents: [] };
  }

  const leagues = await findLeaguesWithActiveSeasonsByUserId(userId);

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

  const leaguesWithData = await Promise.all(
    leagues.map(async (league) => {
      const calendarEvents: CalendarPanelEvent[] = [];

      if (league.currentSeasonId) {
        const [seasonWithSports, myTeam] = await Promise.all([
          findCurrentSeasonWithSports(league.id),
          findTeamByOwnerAndSeason(userId, league.currentSeasonId),
        ]);

        if (myTeam && seasonWithSports?.seasonSports) {
          const participantsBySportsSeason = await getDraftedParticipantsBySportsSeason(
            myTeam.id,
            league.currentSeasonId
          );

          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,
                leagueName: league.name,
                leagueId: league.id,
                sportsSeasonPageUrl: `/leagues/${league.id}/sports-seasons/${ss.id}`,
              }));
            })
          );

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

      return calendarEvents;
    })
  );

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

  return { isLoggedIn: true as const, upcomingCalendarEvents };
}

export default function UpcomingEventsPage({ loaderData }: Route.ComponentProps) {
  const { isLoggedIn, upcomingCalendarEvents } = loaderData;

  if (!isLoggedIn) {
    return (
      <div className="container mx-auto py-16 px-4 text-center">
        <p className="text-muted-foreground">Sign in to see your upcoming events.</p>
      </div>
    );
  }

  return (
    <div className="container mx-auto py-8 px-4 max-w-2xl">
      <div className="mb-6">
        <Link
          to="/"
          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" />
          My Leagues
        </Link>
        <h1 className="text-3xl font-bold">Upcoming Events</h1>
        <p className="text-muted-foreground mt-1">Next 60 days across all your leagues</p>
      </div>

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