import React, { useState, useMemo } from "react";
import {
  Stack,
  Text,
  Group,
  Button,
  Select,
  LoadingOverlay,
  Alert,
  Title,
  Divider,
  Box,
} from "@mantine/core";
import { InfoIcon } from "@phosphor-icons/react";
import { Trans, Plural, useLingui } from "@lingui/react/macro";
import { msg } from "@lingui/core/macro";
import { useServerMutation } from "@/lib/tanstack-query/hooks/use-server-mutation";
import { generateGroupStage } from "../server";
import { TeamInfo } from "@/features/teams/types";
import {
  calculateGroupConfigurations,
  assignTeamsToGroups,
  getGroupName,
  GroupConfigOption,
} from "../utils/group-config";
import {
  formatGroupRankLabel,
  formatWildcardLabel,
} from "@/features/bracket/utils/group-label";
import GroupPreview from "./group-preview";
import { useQueryClient } from "@tanstack/react-query";
import { tournamentKeys } from "../queries";
import brackets from "@/features/bracket/utils";
import { Bracket } from "@/features/bracket/components/bracket";
import { Match } from "@/features/matches/types";
import { generateSingleEliminationBracket } from "../utils/bracket-generator";

interface SetupGroupStageProps {
  tournamentId: string;
  teams: TeamInfo[];
}

const SetupGroupStage: React.FC<SetupGroupStageProps> = ({
  tournamentId,
  teams,
}) => {
  const queryClient = useQueryClient();
  const { t, i18n } = useLingui();

  const [selectedConfigIndex, setSelectedConfigIndex] = useState<string>("0");
  const [seed, setSeed] = useState<number>(Date.now());

  const configurations = useMemo(() => {
    try {
      return calculateGroupConfigurations(i18n, teams.length);
    } catch (error) {
      return [];
    }
  }, [teams.length, i18n]);

  const selectedConfig: GroupConfigOption | null = useMemo(() => {
    const index = parseInt(selectedConfigIndex);
    return configurations[index] || null;
  }, [selectedConfigIndex, configurations]);

  const groupAssignments = useMemo(() => {
    if (!selectedConfig) return [];

    const teamIds = teams.map((t) => t.id);
    const assignments = assignTeamsToGroups(teamIds, selectedConfig, seed);

    return assignments.map((teamIds, index) => ({
      groupIndex: index,
      groupName: getGroupName(index),
      teams: teamIds.map((id) => teams.find((t) => t.id === id)!).filter(Boolean),
      teamIds,
    }));
  }, [selectedConfig, teams, seed]);

  const knockoutTeamCount = useMemo(() => {
    if (!selectedConfig) return 0;
    return selectedConfig.num_groups * selectedConfig.advance_per_group;
  }, [selectedConfig]);

  const bracketPreview = useMemo(() => {
    if (!knockoutTeamCount || !selectedConfig) {
      return null;
    }

    const nextPowerOf2 = Math.pow(2, Math.ceil(Math.log2(knockoutTeamCount)));
    const bracketSize = nextPowerOf2;
    const wildcardsNeeded = bracketSize - knockoutTeamCount;

    let bracketTemplate: any;
    if (Object.keys(brackets).includes(bracketSize.toString())) {
      bracketTemplate = brackets[bracketSize as keyof typeof brackets];
    } else {
      try {
        bracketTemplate = generateSingleEliminationBracket(bracketSize);
      } catch (error) {
        return null;
      }
    }

    const groupNames = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
    const seedLabels: Record<number, string> = {};

    const totalTeams = selectedConfig.num_groups * selectedConfig.advance_per_group;
    let seedIndex = 1;

    for (let i = 0; i < totalTeams / 2; i++) {
      const group1 = i % selectedConfig.num_groups;
      const rankIndex1 = Math.floor(i / selectedConfig.num_groups);
      const rank1 = rankIndex1 + 1;
      const groupName1 = groupNames[group1] ||
        i18n._({ ...msg`Group {n}`, values: { n: group1 + 1 } });
      seedLabels[seedIndex++] = formatGroupRankLabel(i18n, groupName1, rank1);

      const group2 = (i + 1) % selectedConfig.num_groups;
      const rankIndex2 = selectedConfig.advance_per_group - 1 - rankIndex1;
      const rank2 = rankIndex2 + 1;
      const groupName2 = groupNames[group2] ||
        i18n._({ ...msg`Group {n}`, values: { n: group2 + 1 } });
      seedLabels[seedIndex++] = formatGroupRankLabel(i18n, groupName2, rank2);
    }

    for (let i = 0; i < wildcardsNeeded; i++) {
      seedLabels[seedIndex++] = formatWildcardLabel(i18n, i + 1);
    }

    const ordersMap: Record<number, number> = {};
    bracketTemplate.winners.forEach((round: any[]) => {
      round.forEach((match: any) => {
        ordersMap[match.lid] = match.order;
      });
    });

    const placeholderMatches: Match[][] = bracketTemplate.winners.map((round: any[], roundIndex: number) =>
      round.map((match: any) => {
        const matchData: any = {
          ...match,
          id: `preview-${match.lid}`,
          home_from_lid: match.home_from_lid !== null && match.home_from_lid !== undefined ? match.home_from_lid : -1,
          away_from_lid: match.away_from_lid !== null && match.away_from_lid !== undefined ? match.away_from_lid : -1,
          home_cups: 0,
          away_cups: 0,
          status: "tbd" as const,
          tournament: { id: "", name: "" },
        };

        if (roundIndex === 0) {
          matchData.home = match.home_seed && !match.bye ? { id: `seed-${match.home_seed}`, name: seedLabels[match.home_seed] } : null;
          matchData.away = match.away_seed ? { id: `seed-${match.away_seed}`, name: seedLabels[match.away_seed] } : null;
        } else {
          matchData.home = null;
          matchData.away = null;
        }

        return matchData;
      })
    );

    return { matches: placeholderMatches, orders: ordersMap };
  }, [knockoutTeamCount, selectedConfig, i18n]);

  const generateGroups = useServerMutation({
    mutationFn: generateGroupStage,
    successMessage: t`Group stage generated successfully!`,
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: tournamentKeys.details(tournamentId),
      });
    },
  });

  const handleGenerateGroups = () => {
    if (!selectedConfig) return;

    generateGroups.mutate({
      data: {
        tournamentId,
        groupConfig: {
          num_groups: selectedConfig.num_groups,
          teams_per_group: selectedConfig.teams_per_group,
          advance_per_group: selectedConfig.advance_per_group,
          matches_guaranteed: selectedConfig.matches_guaranteed,
          seeding_method: selectedConfig.seeding_method,
        },
        teamAssignments: groupAssignments.map((g) => ({
          groupIndex: g.groupIndex,
          groupName: g.groupName,
          teamIds: g.teamIds,
        })),
        seed,
      },
    });
  };

  const handleShuffle = () => {
    setSeed(Date.now());
  };

  if (configurations.length === 0) {
    return (
      <Alert color="red" title={t`Cannot create groups`} icon={<InfoIcon />}>
        <Trans>
          Need at least 4 teams to create a group stage format. Current team count: {teams.length}
        </Trans>
      </Alert>
    );
  }

  return (
    <div style={{ display: "flex", gap: "2rem", alignItems: "flex-start" }}>
      <Stack gap="lg" style={{ flexShrink: 0, width: 400 }}>
        <Stack gap={0} pos="relative">
          <LoadingOverlay visible={generateGroups.isPending} />

          <Group gap="xs" p="md" pb="sm" align="center">
            <Text fw={600} size="lg">
              <Trans>Group Stage Setup</Trans>
            </Text>
            <Text size="sm" c="dimmed" ml="auto">
              <Plural value={teams.length} one="# team" other="# teams" />
            </Text>
          </Group>

          <Stack gap="md" p="md" pt={0}>
            <Stack gap="xs">
              <Text size="sm" fw={500}>
                <Trans>Group Configuration</Trans>
              </Text>
              <Select
                value={selectedConfigIndex}
                onChange={(value) => setSelectedConfigIndex(value || "0")}
                data={configurations.map((config, index) => ({
                  value: index.toString(),
                  label: config.description,
                }))}
                styles={{
                  dropdown: { maxHeight: 300, overflowY: "auto" },
                }}
              />
            </Stack>

            {selectedConfig && (
              <Stack gap="xs">
                <Text size="xs" c="dimmed">
                  <Plural
                    value={selectedConfig.total_group_matches}
                    one="# total group stage match"
                    other="# total group stage matches"
                  />
                </Text>
                {selectedConfig.wildcards_needed > 0 && (
                  <Text size="xs" c="yellow">
                    ⚠{" "}
                    <Plural
                      value={selectedConfig.wildcards_needed}
                      one="# wildcard spot needed for knockout bracket"
                      other="# wildcard spots needed for knockout bracket"
                    />
                  </Text>
                )}
              </Stack>
            )}

            <Button size="sm" variant="light" onClick={handleShuffle}>
              <Trans>Shuffle Groups</Trans>
            </Button>

            <Button
              size="sm"
              onClick={handleGenerateGroups}
              loading={generateGroups.isPending}
              disabled={!selectedConfig}
            >
              <Trans>Confirm Setup</Trans>
            </Button>
          </Stack>
        </Stack>
      </Stack>

      <div style={{ flex: 1, overflow: "auto", maxHeight: "80vh" }}>
        <Stack gap="xl">
          {groupAssignments.length > 0 && (
            <GroupPreview groups={groupAssignments} />
          )}

          {bracketPreview && knockoutTeamCount > 0 && (
            <Box>
              <Divider mb="lg" />
              <Title order={3} ta="center" mb="md">
                <Trans>
                  Knockout Bracket Preview ({selectedConfig?.knockout_size} Teams)
                </Trans>
              </Title>
              <Text size="sm" c="dimmed" ta="center" mb="lg">
                <Trans>
                  Top{" "}
                  <Plural
                    value={selectedConfig?.advance_per_group ?? 0}
                    one="# team"
                    other="# teams"
                  />{" "}
                  from each group will advance
                  {selectedConfig?.wildcards_needed ? (
                    <>
                      {" + "}
                      <Plural
                        value={selectedConfig.wildcards_needed}
                        one="# wildcard"
                        other="# wildcards"
                      />
                    </>
                  ) : (
                    ""
                  )}
                </Trans>
              </Text>
              <Box
                style={{
                  backgroundImage: `radial-gradient(circle, var(--mantine-color-default-border) 1px, transparent 1px)`,
                  backgroundSize: "16px 16px",
                  backgroundPosition: "0 0, 8px 8px",
                  padding: "1rem",
                  borderRadius: "8px",
                }}
              >
                <Bracket
                  rounds={bracketPreview.matches}
                  orders={bracketPreview.orders}
                  showControls={false}
                />
              </Box>
            </Box>
          )}
        </Stack>
      </div>
    </div>
  );
};

export default SetupGroupStage;
