import React, { useMemo, useState } from "react";
import { Stack, Text, Card, Group as MantineGroup, Box, SimpleGrid, Tabs, Collapse, ActionIcon, Button, Alert, Badge } from "@mantine/core";
import { CaretCircleDownIcon, CaretCircleUpIcon } from "@phosphor-icons/react";
import { Match } from "@/features/matches/types";
import { Group, GroupConfig } from "../types";
import GroupMatchCard from "./group-match-card";
import TeamAvatar from "@/components/team-avatar";
import { useServerMutation } from "@/lib/tanstack-query/hooks/use-server-mutation";
import { populateKnockoutBracket } from "@/features/matches/server";
import { useQueryClient } from "@tanstack/react-query";
import { tournamentKeys } from "../queries";
import { computeGroupStageOrder } from "../utils/match-queue";
import { Trans, useLingui } from "@lingui/react/macro";

interface GroupStageViewProps {
  groups: Group[];
  matches: Match[];
  showControls?: boolean;
  tournamentId?: string;
  hasKnockoutBracket?: boolean;
  isRegional?: boolean;
  groupConfig?: GroupConfig;
  nextUpMatchId?: string;
}

interface TeamStanding {
  teamId: string;
  teamName: string;
  team: any;
  wins: number;
  losses: number;
  cupsFor: number;
  cupsAgainst: number;
  cupDifference: number;
}

const GroupStageView: React.FC<GroupStageViewProps> = ({
  groups,
  matches,
  showControls,
  tournamentId,
  hasKnockoutBracket,
  isRegional,
  groupConfig,
  nextUpMatchId,
}) => {
  const { t } = useLingui();
  const queryClient = useQueryClient();
  const [expandedTeams, setExpandedTeams] = useState<Record<string, boolean>>({});

  const populateKnockoutMutation = useServerMutation({
    mutationFn: populateKnockoutBracket,
    successMessage: t`Knockout bracket populated successfully!`,
    onSuccess: () => {
      if (tournamentId) {
        queryClient.invalidateQueries({ queryKey: tournamentKeys.details(tournamentId) });
      }
    },
  });

  const allGroupMatchesCompleted = useMemo(() => {
    const groupMatches = matches.filter((match) => match.round === -1);
    if (groupMatches.length === 0) return false;
    return groupMatches.every((match) => match.status === "ended");
  }, [matches]);

  const handlePopulateKnockout = () => {
    if (!tournamentId) return;
    populateKnockoutMutation.mutate({ data: { tournamentId } });
  };

  const globalOrderRank = useMemo(() => {
    const groupMatches = matches.filter((match) => match.round === -1 && match.group);
    const order = computeGroupStageOrder(
      groupMatches.map((m) => ({
        groupId: m.group ?? "",
        teamA: m.home?.id ?? "",
        teamB: m.away?.id ?? "",
      })),
    );

    const rank = new Map<string, number>();
    order.forEach((matchIdx, position) => {
      rank.set(groupMatches[matchIdx].id, position);
    });
    return rank;
  }, [matches]);

  const matchesByGroup = useMemo(() => {
    const map = new Map<string, Match[]>();

    matches
      .filter((match) => match.round === -1 && match.group)
      .forEach((match) => {
        if (!map.has(match.group!)) {
          map.set(match.group!, []);
        }
        map.get(match.group!)!.push(match);
      });

    map.forEach((groupMatches, groupId) => {
      const sorted = [...groupMatches].sort(
        (a, b) => (globalOrderRank.get(a.id) ?? 0) - (globalOrderRank.get(b.id) ?? 0),
      );
      map.set(groupId, sorted);
    });

    return map;
  }, [matches, globalOrderRank]);

  const sortedGroups = useMemo(() => {
    return [...groups].sort((a, b) => a.order - b.order);
  }, [groups]);

  const toggleTeams = (groupId: string) => {
    setExpandedTeams((prev) => ({
      ...prev,
      [groupId]: !prev[groupId],
    }));
  };

  const getTeamStandings = (groupId: string, teams: any[]): TeamStanding[] => {
    const groupMatches = matchesByGroup.get(groupId) || [];
    const standings: Map<string, TeamStanding> = new Map();

    teams.forEach((team) => {
      standings.set(team.id, {
        teamId: team.id,
        teamName: team.name,
        team: team,
        wins: 0,
        losses: 0,
        cupsFor: 0,
        cupsAgainst: 0,
        cupDifference: 0,
      });
    });

    const completedMatches = groupMatches.filter((match) => match.status === "ended");

    completedMatches.forEach((match) => {
      const homeId = match.home?.id;
      const awayId = match.away?.id;

      if (!homeId || !awayId) return;

      const homeStanding = standings.get(homeId);
      const awayStanding = standings.get(awayId);

      if (!homeStanding || !awayStanding) return;

      const homeCups = match.home_cups || 0;
      const awayCups = match.away_cups || 0;

      homeStanding.cupsFor += homeCups;
      homeStanding.cupsAgainst += awayCups;
      awayStanding.cupsFor += awayCups;
      awayStanding.cupsAgainst += homeCups;

      homeStanding.cupDifference += homeCups - awayCups;
      awayStanding.cupDifference += awayCups - homeCups;

      if (homeCups > awayCups) {
        homeStanding.wins++;
        awayStanding.losses++;
      } else if (awayCups > homeCups) {
        awayStanding.wins++;
        homeStanding.losses++;
      }
    });

    const h2hRecords = new Map<string, Map<string, { wins: number; cupDiff: number }>>();

    completedMatches.forEach((match) => {
      const homeId = match.home?.id;
      const awayId = match.away?.id;

      if (!homeId || !awayId) return;

      if (!h2hRecords.has(homeId)) {
        h2hRecords.set(homeId, new Map());
      }
      if (!h2hRecords.has(awayId)) {
        h2hRecords.set(awayId, new Map());
      }

      const homeH2H = h2hRecords.get(homeId)!;
      const awayH2H = h2hRecords.get(awayId)!;

      if (!homeH2H.has(awayId)) {
        homeH2H.set(awayId, { wins: 0, cupDiff: 0 });
      }
      if (!awayH2H.has(homeId)) {
        awayH2H.set(homeId, { wins: 0, cupDiff: 0 });
      }

      const homeRecord = homeH2H.get(awayId)!;
      const awayRecord = awayH2H.get(homeId)!;

      const homeCups = match.home_cups || 0;
      const awayCups = match.away_cups || 0;

      const cupDiff = homeCups - awayCups;
      homeRecord.cupDiff += cupDiff;
      awayRecord.cupDiff -= cupDiff;

      if (homeCups > awayCups) {
        homeRecord.wins++;
      } else if (awayCups > homeCups) {
        awayRecord.wins++;
      }
    });

    return Array.from(standings.values()).sort((a, b) => {
      if (b.wins !== a.wins) return b.wins - a.wins;

      if (b.cupDifference !== a.cupDifference) return b.cupDifference - a.cupDifference;

      if (b.cupsFor !== a.cupsFor) return b.cupsFor - a.cupsFor;

      const aH2H = h2hRecords.get(a.teamId);
      const bH2H = h2hRecords.get(b.teamId);

      if (aH2H && bH2H) {
        const aVsB = aH2H.get(b.teamId);
        const bVsA = bH2H.get(a.teamId);

        if (aVsB && bVsA) {
          if (aVsB.wins !== bVsA.wins) return bVsA.wins - aVsB.wins;

          if (aVsB.cupDiff !== -bVsA.cupDiff) return aVsB.cupDiff - (-bVsA.cupDiff);
        }
      }

      return a.teamId.localeCompare(b.teamId);
    });
  };

  const allGroupStandings = useMemo(() => {
    return sortedGroups.map((group) => ({
      groupId: group.id,
      groupOrder: group.order,
      standings: getTeamStandings(group.id, group.teams || []),
    }));
  }, [sortedGroups, matchesByGroup]);

  const advancingTeams = useMemo(() => {
    if (!groupConfig) return { qualifiedTeams: new Set<string>(), wildcardTeams: new Set<string>() };

    const advancePerGroup = groupConfig.advance_per_group;
    const qualifiedTeams = new Set<string>();
    const wildcardTeams = new Set<string>();

    allGroupStandings.forEach(({ standings }) => {
      standings.slice(0, advancePerGroup).forEach((standing) => {
        qualifiedTeams.add(standing.teamId);
      });
    });

    const totalQualified = qualifiedTeams.size;
    const knockoutTeamCount = totalQualified;

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

    if (wildcardsNeeded > 0) {
      const allNonQualifiedTeams: TeamStanding[] = [];

      allGroupStandings.forEach(({ standings }) => {
        standings.slice(advancePerGroup).forEach((standing) => {
          allNonQualifiedTeams.push(standing);
        });
      });

      allNonQualifiedTeams.sort((a, b) => {
        if (b.wins !== a.wins) return b.wins - a.wins;
        if (b.cupDifference !== a.cupDifference) return b.cupDifference - a.cupDifference;
        if (b.cupsFor !== a.cupsFor) return b.cupsFor - a.cupsFor;
        return a.teamId.localeCompare(b.teamId);
      });

      allNonQualifiedTeams.slice(0, wildcardsNeeded).forEach((standing) => {
        wildcardTeams.add(standing.teamId);
      });
    }

    return { qualifiedTeams, wildcardTeams };
  }, [allGroupStandings, groupConfig]);

  if (sortedGroups.length === 0) {
    return (
      <Box p="md">
        <Text size="sm" c="dimmed" ta="center">
          <Trans>No groups have been created yet</Trans>
        </Text>
      </Box>
    );
  }

  const showGenerateKnockoutButton = showControls && tournamentId && !hasKnockoutBracket && allGroupMatchesCompleted;

  return (
    <Box p="md">
      <Stack gap="md">
        {showGenerateKnockoutButton && (
          <Alert color="blue" title={t`Group Stage Complete`} icon={<CaretCircleUpIcon size={20} />}>
            <Stack gap="xs">
              <Text size="sm"><Trans>All group matches are finished! Populate the knockout bracket to advance qualified teams.</Trans></Text>
              <Button
                onClick={handlePopulateKnockout}
                loading={populateKnockoutMutation.isPending}
                size="sm"
              >
                <Trans>Populate Knockout Bracket</Trans>
              </Button>
            </Stack>
          </Alert>
        )}
        <Tabs defaultValue={sortedGroups[0]?.id}>
        <Tabs.List mb="md" grow>
          {sortedGroups.map((group) => {
            const groupMatches = matchesByGroup.get(group.id) || [];
            const completedMatches = groupMatches.filter((m) => m.status === "ended").length;
            const totalMatches = groupMatches.length;

            return (
              <Tabs.Tab
                key={group.id}
                value={group.id}
                style={{
                  padding: '12px 20px',
                }}
              >
                <MantineGroup gap="xs" justify="center" wrap="nowrap">
                  <Text fw={600} size="sm"><Trans>Group {group.name}</Trans></Text>
                  <Text size="xs" c="dimmed" style={{ opacity: 0.7 }}>
                    ({completedMatches}/{totalMatches})
                  </Text>
                </MantineGroup>
              </Tabs.Tab>
            );
          })}
        </Tabs.List>

        {sortedGroups.map((group) => {
          const groupMatches = matchesByGroup.get(group.id) || [];
          const standings = getTeamStandings(group.id, group.teams || []);

          return (
            <Tabs.Panel key={group.id} value={group.id}>
              <Stack gap="md">
                <Card withBorder radius="md" p={0}>
                  <MantineGroup
                    justify="space-between"
                    p="sm"
                    style={{
                      cursor: 'pointer',
                      backgroundColor: 'var(--mantine-color-default-hover)',
                    }}
                    onClick={() => toggleTeams(group.id)}
                  >
                    <Text fw={600} size="sm">
                      <Trans>Standings ({standings.length})</Trans>
                    </Text>
                    <ActionIcon
                      variant="subtle"
                      size="sm"
                      aria-label={expandedTeams[group.id] ? t`Collapse standings` : t`Expand standings`}
                    >
                      {expandedTeams[group.id] ? <CaretCircleUpIcon size={16} /> : <CaretCircleDownIcon size={16} />}
                    </ActionIcon>
                  </MantineGroup>
                  <Collapse in={expandedTeams[group.id]}>
                    <Stack gap={0}>
                      {standings.length > 0 ? (
                        standings.map((standing, index) => {
                          const isQualified = advancingTeams.qualifiedTeams.has(standing.teamId);
                          const isWildcard = advancingTeams.wildcardTeams.has(standing.teamId);
                          const isAdvancing = isQualified || isWildcard;

                          return (
                            <MantineGroup
                              key={standing.teamId}
                              gap="sm"
                              align="center"
                              wrap="nowrap"
                              px="md"
                              py="xs"
                              style={{
                                borderTop: index > 0 ? '1px solid var(--mantine-color-default-border)' : 'none',
                                backgroundColor: isAdvancing ? 'var(--mantine-primary-color-light)' : undefined,
                                borderLeft: isAdvancing ? '3px solid var(--mantine-primary-color-filled)' : '3px solid transparent',
                              }}
                            >
                              <Text size="sm" fw={700} c="dimmed" w={24} ta="center">
                                {index + 1}
                              </Text>
                              <TeamAvatar team={standing.team} size={28} radius="sm" isRegional={isRegional} />
                              <Box style={{ flex: 1, minWidth: 0 }}>
                                <Text size="sm" fw={500} lineClamp={1}>
                                  {standing.teamName}
                                </Text>
                              </Box>
                              <MantineGroup gap="xs" wrap="nowrap">
                                {isWildcard && (
                                  <Badge size="xs" color="yellow" variant="light">
                                    <Trans>WC</Trans>
                                  </Badge>
                                )}
                                {isQualified && (
                                  <Badge size="xs" variant="light">
                                    <Trans>Q</Trans>
                                  </Badge>
                                )}
                                <Text size="xs" c="dimmed" fw={500} miw={35} ta="center">
                                  {standing.wins}-{standing.losses}
                                </Text>
                                <Text
                                  size="xs"
                                  c={standing.cupDifference > 0 ? "green" : standing.cupDifference < 0 ? "red" : "dimmed"}
                                  fw={600}
                                  miw={30}
                                  ta="center"
                                >
                                  {standing.cupDifference > 0 ? '+' : ''}{standing.cupDifference}
                                </Text>
                                <Text size="xs" c="dimmed" fw={400} miw={40} ta="center">
                                  {standing.cupsFor}/{standing.cupsAgainst}
                                </Text>
                              </MantineGroup>
                            </MantineGroup>
                          );
                        })
                      ) : (
                        <Text size="sm" c="dimmed" ta="center" py="md">
                          <Trans>No teams assigned</Trans>
                        </Text>
                      )}
                    </Stack>
                  </Collapse>
                </Card>

                {groupMatches.length === 0 ? (
                  <Card withBorder radius="md" p="xl">
                    <Text size="sm" c="dimmed" ta="center">
                      <Trans>No matches scheduled</Trans>
                    </Text>
                  </Card>
                ) : (
                  <SimpleGrid
                    cols={{ base: 1, sm: 2, lg: 3 }}
                    spacing="md"
                  >
                    {groupMatches.map((match) => (
                      <GroupMatchCard
                        key={match.id}
                        match={match}
                        showControls={showControls}
                        nextUpMatchId={nextUpMatchId}
                      />
                    ))}
                  </SimpleGrid>
                )}
              </Stack>
            </Tabs.Panel>
          );
        })}
      </Tabs>
      </Stack>
    </Box>
  );
};

export default GroupStageView;
