import { createFileRoute, redirect } from "@tanstack/react-router";
import {
  tournamentQueries,
  useTournament,
} from "@/features/tournaments/queries";
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
import SeedTournament from "@/features/tournaments/components/seed-tournament";
import SetupGroupStage from "@/features/tournaments/components/setup-group-stage";
import GroupStageView from "@/features/tournaments/components/group-stage-view";
import { Container, Stack, Divider, Title, Box, Card, Group, Skeleton, SimpleGrid } from "@mantine/core";
import { useMemo } from "react";
import { BracketData } from "@/features/bracket/types";
import { Match } from "@/features/matches/types";
import BracketView from "@/features/bracket/components/bracket-view";
import { SpotifyControlsBar } from "@/features/spotify/components";
import { useAuth } from "@/contexts/auth-context";
import { Trans } from "@lingui/react/macro";
import { msg } from "@lingui/core/macro";

export const Route = createFileRoute("/_authed/admin/tournaments/run/$id")({
  beforeLoad: async ({ context, params }) => {
    const { queryClient } = context;
    const tournament = await ensureServerQueryData(
      queryClient,
      tournamentQueries.details(params.id)
    );
    if (!tournament) throw redirect({ to: "/admin/tournaments" });
    return {
      tournament,
    };
  },
  loader: ({ context }) => ({
    fullWidth: true,
    withPadding: false,
    showSpotifyPanel: true,
    header: {
      withBackButton: true,
      title: msg`Run {name}`,
      titleValues: { name: context.tournament.name },
    },
  }),
  component: RouteComponent,
  pendingComponent: RunTournamentPending,
});

function RunTournamentPending() {
  return (
    <Container size="md" px={0}>
      <Box p="md">
        <Stack gap="md">
          <Group gap={0} grow mb="md">
            {Array.from({ length: 4 }).map((_, index) => (
              <Skeleton
                key={`run-pending-tab-${index}`}
                height={44}
                radius="sm"
                style={{ opacity: 0.85 - index * 0.1 }}
              />
            ))}
          </Group>
          <Card withBorder radius="md" p={0}>
            <Group justify="space-between" p="sm">
              <Skeleton height={16} width={120} radius="sm" />
              <Skeleton height={22} width={22} radius="xl" />
            </Group>
          </Card>
          <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md">
            {Array.from({ length: 6 }).map((_, index) => (
              <Skeleton
                key={`run-pending-match-${index}`}
                height={100}
                radius="md"
                style={{ opacity: Math.max(1 - index * 0.12, 0.4) }}
              />
            ))}
          </SimpleGrid>
        </Stack>
      </Box>
    </Container>
  );
}

function RouteComponent() {
  const { id } = Route.useParams();
  const { data: tournament } = useTournament(id);
  const { roles } = useAuth();
  const isAdmin = roles?.includes('Admin') || false;

  const hasGroupStage = useMemo(() => {
    return tournament.matches?.some((match) => match.round === -1) || false;
  }, [tournament.matches]);

  const hasKnockout = useMemo(() => {
    return tournament.matches?.some((match) => match.round !== -1) || false;
  }, [tournament.matches]);

  const knockoutBracketPopulated = useMemo(() => {
    return tournament.matches?.some((match) =>
      match.round === 0 && match.lid >= 0 && (match.home || match.away)
    ) || false;
  }, [tournament.matches]);

  const nextUpMatchId = useMemo(() => {
    const ready = (tournament.matches ?? [])
      .filter(
        (match) =>
          match.status === "ready" && match.home && match.away && !match.bye
      )
      .sort((a, b) => a.order - b.order);
    return ready[0]?.id;
  }, [tournament.matches]);

  const bracket: BracketData = useMemo(() => {
    if (!tournament.matches || tournament.matches.length === 0) {
      return { winners: [], losers: [] };
    }

    const winnersMap = new Map<number, Match[]>();
    const losersMap = new Map<number, Match[]>();

    tournament.matches
      .filter((match) => match.round !== -1)
      .sort((a, b) => a.lid - b.lid)
      .forEach((match) => {
        if (!match.is_losers_bracket) {
          if (!winnersMap.has(match.round)) {
            winnersMap.set(match.round, []);
          }
          winnersMap.get(match.round)!.push(match);
        } else {
          if (!losersMap.has(match.round)) {
            losersMap.set(match.round, []);
          }
          losersMap.get(match.round)!.push(match);
        }
      });

    const winners = Array.from(winnersMap.entries())
      .sort(([a], [b]) => a - b)
      .map(([, matches]) => matches);

    const losers = Array.from(losersMap.entries())
      .sort(([a], [b]) => a - b)
      .map(([, matches]) => matches);
    return { winners, losers };
  }, [tournament.matches]);

  return (
    <Container size="md" px={0}>
      { isAdmin && !tournament.regional && <SpotifyControlsBar />}
      {tournament.matches?.length ? (
        hasGroupStage && hasKnockout ? (
          <Stack gap="xl">
            <GroupStageView
              groups={tournament.groups || []}
              matches={tournament.matches}
              showControls
              tournamentId={tournament.id}
              hasKnockoutBracket={knockoutBracketPopulated}
              isRegional={tournament.regional}
              groupConfig={tournament.group_config}
              nextUpMatchId={nextUpMatchId}
            />
            <Divider />
            <div>
              <Title order={3} ta="center" mb="md"><Trans>Knockout Bracket</Trans></Title>
              <BracketView bracket={bracket} showControls groupConfig={tournament.group_config} nextUpMatchId={nextUpMatchId} />
            </div>
          </Stack>
        ) : hasGroupStage ? (
          <GroupStageView
            groups={tournament.groups || []}
            matches={tournament.matches}
            showControls
            tournamentId={tournament.id}
            hasKnockoutBracket={knockoutBracketPopulated}
            isRegional={tournament.regional}
            groupConfig={tournament.group_config}
            nextUpMatchId={nextUpMatchId}
          />
        ) : (
          <BracketView bracket={bracket} showControls groupConfig={tournament.group_config} nextUpMatchId={nextUpMatchId} />
        )
      ) : (
        tournament.regional === true ? (
          <SetupGroupStage
            tournamentId={tournament.id}
            teams={tournament.teams || []}
          />
        ) : (
          <SeedTournament
            tournamentId={tournament.id}
            teams={tournament.teams || []}
            isRegional={tournament.regional}
          />
        )
      )}
    </Container>
  );
}
