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 { 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 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 [selectedConfigIndex, setSelectedConfigIndex] = useState<string>("0");
  const [seed, setSeed] = useState<number>(Date.now());

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

  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;
    }

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

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

    let seedIndex = 1;
    for (let rank = 1; rank <= selectedConfig.advance_per_group; rank++) {
      for (let groupIdx = 0; groupIdx < selectedConfig.num_groups; groupIdx++) {
        const groupName = groupNames[groupIdx] || `Group ${groupIdx + 1}`;
        const rankSuffix = rank === 1 ? '1st' : rank === 2 ? '2nd' : rank === 3 ? '3rd' : `${rank}th`;
        seedLabels[seedIndex++] = `${groupName} ${rankSuffix}`;
      }
    }

    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]);

  const generateGroups = useServerMutation({
    mutationFn: generateGroupStage,
    successMessage: "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="Cannot create groups" icon={<InfoIcon />}>
        Need at least 4 teams to create a group stage format. Current team count: {teams.length}
      </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">
              Group Stage Setup
            </Text>
            <Text size="sm" c="dimmed" ml="auto">
              {teams.length} teams
            </Text>
          </Group>

          <Stack gap="md" p="md" pt={0}>
            <Stack gap="xs">
              <Text size="sm" fw={500}>
                Group Configuration
              </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">
                  {selectedConfig.total_group_matches} total group stage matches
                </Text>
                {selectedConfig.wildcards_needed > 0 && (
                  <Text size="xs" c="yellow">
                    ⚠ {selectedConfig.wildcards_needed} wildcard spot{selectedConfig.wildcards_needed > 1 ? 's' : ''} needed for knockout bracket
                  </Text>
                )}
              </Stack>
            )}

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

            <Button
              size="sm"
              onClick={handleGenerateGroups}
              loading={generateGroups.isPending}
              disabled={!selectedConfig}
            >
              Confirm Setup
            </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">
                Knockout Bracket Preview ({knockoutTeamCount} Teams)
              </Title>
              <Text size="sm" c="dimmed" ta="center" mb="lg">
                Top {selectedConfig?.advance_per_group} team{selectedConfig?.advance_per_group !== 1 ? 's' : ''} from each group will advance
              </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;
