import { createFileRoute, redirect, useNavigate } from "@tanstack/react-router";
import { tournamentQueries, useFreeAgents, useTournament } from "@/features/tournaments/queries";
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
import { Stack, Text, Button, Alert, LoadingOverlay, Group, Skeleton } from "@mantine/core";
import { useState } from "react";
import useGenerateRandomTeams from "@/features/tournaments/hooks/use-generate-random-teams";
import useConfirmTeamAssignments from "@/features/tournaments/hooks/use-confirm-team-assignments";
import TeamAssignmentPreview from "@/features/tournaments/components/team-assignment-preview";
import { WarningCircleIcon, ShuffleIcon, CheckCircleIcon } from "@phosphor-icons/react";
import { PlayerInfo } from "@/features/players/types";
import { useQueryClient } from "@tanstack/react-query";
import { Trans, Plural } from "@lingui/react/macro";
import { msg } from "@lingui/core/macro";

export const Route = createFileRoute("/_authed/admin/tournaments/$id/assign-partners")({
  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 }) => ({
    header: {
      withBackButton: true,
      title: msg`Manage {name}`,
      titleValues: { name: context.tournament.name },
    },
  }),
  component: RouteComponent,
  pendingComponent: AssignPartnersPending,
});

function AssignPartnersPending() {
  return (
    <Stack gap="lg">
      <Stack gap="xs">
        <Group gap="xs" align="baseline">
          <Skeleton height={28} width={36} radius="sm" />
          <Skeleton height={14} width={110} radius="sm" />
        </Group>
        <Skeleton height={36} w="100%" radius="sm" style={{ opacity: 0.7 }} />
      </Stack>
    </Stack>
  );
}

interface TeamAssignment {
  player1: PlayerInfo;
  player2: PlayerInfo;
  teamName: string;
}

function RouteComponent() {
  const { id } = Route.useParams();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const { data: freeAgents } = useFreeAgents(id);
  const [assignments, setAssignments] = useState<TeamAssignment[] | null>(null);
  const [currentSeed, setCurrentSeed] = useState<number | undefined>(undefined);

  const generateMutation = useGenerateRandomTeams();
  const confirmMutation = useConfirmTeamAssignments();

  const hasOddPlayers = freeAgents.length % 2 !== 0;
  const hasEnoughPlayers = freeAgents.length >= 2;

  const handleGenerate = () => {
    generateMutation.mutate(
      { data: { tournamentId: id, seed: currentSeed } },
      {
        onSuccess: (result) => {
          setAssignments(result.assignments);
          setCurrentSeed(result.seed);
        },
      }
    );
  };

  const handleReroll = () => {
    if (currentSeed === undefined) return;
    generateMutation.mutate(
      { data: { tournamentId: id, seed: currentSeed + 1 } },
      {
        onSuccess: (result) => {
          setAssignments(result.assignments);
          setCurrentSeed(result.seed);
        },
      }
    );
  };

  const handleConfirm = () => {
    if (!assignments) return;

    const formattedAssignments = assignments.map((a) => ({
      player1Id: a.player1.id,
      player2Id: a.player2.id,
      teamName: a.teamName,
    }));

    confirmMutation.mutate(
      { data: { tournamentId: id, assignments: formattedAssignments } },
      {
        onSuccess: () => {
          queryClient.invalidateQueries({ queryKey: tournamentQueries.details(id).queryKey });
          queryClient.invalidateQueries({ queryKey: tournamentQueries.free_agents(id).queryKey });
          navigate({ to: "/admin/tournaments/$id", params: { id } });
        },
      }
    );
  };

  return (
    <Stack gap="lg" pos="relative">
      <LoadingOverlay visible={confirmMutation.isPending} />

      <Stack gap="xs">
        <Group gap="xs" align="baseline">
          <Text size="xl" fw={700}>
            {freeAgents.length}
          </Text>
          <Text size="sm" c="dimmed">
            <Plural value={freeAgents.length} one="player enrolled" other="players enrolled" />
          </Text>
        </Group>

        {!hasEnoughPlayers && (
          <Alert color="yellow" icon={<WarningCircleIcon size={16} />}>
            <Trans>Need at least 2 players to create teams</Trans>
          </Alert>
        )}

        {hasOddPlayers && (
          <Alert color="red" icon={<WarningCircleIcon size={16} />}>
            <Trans>Cannot create teams with an odd number of players. Please have one player unenroll.</Trans>
          </Alert>
        )}

        {!assignments && hasEnoughPlayers && !hasOddPlayers && (
          <Button
            leftSection={<ShuffleIcon size={18} />}
            onClick={handleGenerate}
            loading={generateMutation.isPending}
          >
            <Trans>Generate Random Pairings</Trans>
          </Button>
        )}
      </Stack>

      {assignments && (
        <Stack gap="md">
          <Group justify="space-between" align="center">
            <Text size="lg" fw={600}>
              <Trans>Partner Assignments</Trans>
            </Text>
            <Group gap="sm">
              <Button
                variant="subtle"
                leftSection={<ShuffleIcon size={16} />}
                onClick={handleReroll}
                loading={generateMutation.isPending}
                size="sm"
              >
                <Trans>Re-roll</Trans>
              </Button>
              <Button
                leftSection={<CheckCircleIcon size={18} />}
                onClick={handleConfirm}
                loading={confirmMutation.isPending}
                size="sm"
              >
                <Trans>Confirm & Create Teams</Trans>
              </Button>
            </Group>
          </Group>

          <TeamAssignmentPreview assignments={assignments} />
        </Stack>
      )}
    </Stack>
  );
}
