import {
  Stack,
  Container,
  Title,
  Box,
  Divider,
  Text,
  Grid,
  UnstyledButton,
} from '@mantine/core';
import { useAllBadges, useAllEarnedBadges } from '../queries';
import { BadgeIcon } from './badge-showcase';
import { useMemo } from 'react';
import { Badge, EarnedBadge } from '../types';
import { useAllPlayers } from '@/features/teams/hooks/use-available-players';
import { useSheet } from '@/hooks/use-sheet';
import Sheet from '@/components/sheet/sheet';
import PlayerList from '@/features/players/components/player-list';
import { useAuth } from '@/contexts/auth-context';
import { Player } from '@/features/players/types';
import { Trans, useLingui } from '@lingui/react/macro';

const BadgeStatsTable = () => {
  const { data: allBadges } = useAllBadges();
  const { data: allEarnedBadges } = useAllEarnedBadges();
  const { data: allPlayers } = useAllPlayers();
  const totalNumPlayers = allPlayers?.length || 0;

  const groupedEarnedBadges = useMemo(() => {
    const returnDict = new Map<string, EarnedBadge[]>();
    allEarnedBadges?.forEach((earnedBadge) => {
      if (!returnDict.has(earnedBadge.badge)) {
        returnDict.set(earnedBadge.badge, []);
      }
      returnDict.get(earnedBadge.badge)!.push(earnedBadge);
    });
    return returnDict;
  }, [allEarnedBadges]);

  if (allBadges.length === 0) {
    return (
      <Container px={0} size='md'>
        <Stack align='center' gap='md' py='xl'>
          <Title order={3} c='dimmed'>
            <Trans>No Badges Available</Trans>
          </Title>
        </Stack>
      </Container>
    );
  }

  return (
    <Container size='100%' px={0}>
      <Stack gap='xs'>
        <Stack gap={0}>
          {allBadges.map((badge, index) => (
            <BadgeStatRow
              badge={badge}
              totalNumPlayers={totalNumPlayers}
              earnedBadges={groupedEarnedBadges.get(badge.id) || []}
              isLastRow={index >= allBadges.length - 1}
            />
          ))}
        </Stack>
      </Stack>
    </Container>
  );
};

export default BadgeStatsTable;

interface BadgeStatRowProps {
  badge: Badge;
  totalNumPlayers: number;
  earnedBadges: EarnedBadge[];
  isLastRow: boolean;
}

const BadgeStatRow: React.FC<BadgeStatRowProps> = ({
  badge,
  totalNumPlayers,
  earnedBadges,
  isLastRow,
}) => {
  const badgeSheet = useSheet();
  const { user } = useAuth();
  const { t } = useLingui();

  const playerNamesBlurb = useMemo(() => {
    if (earnedBadges.length === 0) return t`No players yet`;

    const currentUserHasBadge = earnedBadges.some(
      (eb) => eb.player.id === user?.id
    );

    const otherPlayers = earnedBadges.filter(
      (eb) => eb.player.id !== user?.id
    );

    const displayPlayers = currentUserHasBadge
      ? otherPlayers.slice(0, 2)
      : earnedBadges.slice(0, 3);

    const names = displayPlayers.map((eb) => eb.player.first_name);
    const namesList = names.join(', ');

    if (currentUserHasBadge) {
      const remaining = earnedBadges.length - 1 - names.length;
      if (names.length === 0 && remaining === 0) {
        return t`You`;
      } else if (names.length === 0 && remaining > 0) {
        return remaining > 1
          ? t`You and ${remaining} others`
          : t`You and 1 other`;
      } else if (remaining > 0) {
        return remaining > 1
          ? t`You, ${namesList} and ${remaining} others`
          : t`You, ${namesList} and 1 other`;
      } else {
        return names.length > 0 ? t`You and ${namesList}` : t`You`;
      }
    } else {
      const remaining = earnedBadges.length - names.length;
      if (remaining > 0) {
        return remaining > 1
          ? t`${namesList} and ${remaining} others`
          : t`${namesList} and 1 other`;
      } else {
        return namesList;
      }
    }
  }, [earnedBadges, user?.id, t]);

  const playersForList: Player[] = useMemo(() => {
    return earnedBadges.map((eb) => ({
      id: eb.player.id,
      first_name: eb.player.first_name,
      last_name: eb.player.last_name,
    } as Player));
  }, [earnedBadges]);

  return (
    <Box key={badge.id}>
      <UnstyledButton onClick={badgeSheet.open} w='100%'>
        <Grid p={'xs'} align='center'>
          <Grid.Col span={2} style={{ display: 'flex', alignItems: 'center' }}>
            <BadgeIcon badge={badge} filled={true} />
          </Grid.Col>
          <Grid.Col span={'auto'}>
            <Stack gap={2}>
              <Text fw={700}>{badge.name}</Text>
              <Text size="sm" fw={500}>{badge.description}</Text>
              <Text size='xs' c='dimmed' mt={4}>
                {playerNamesBlurb}
              </Text>
            </Stack>
          </Grid.Col>
          <Grid.Col
            style={{
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'flex-end',
              width: '73px',
              flexBasis: '73px', // ensures the width is respected
            }}
          >
            <Stack gap={0} align='center'>
              <Text c="dimmed" size='lg' fw={700}>
                {(
                  ((earnedBadges?.length ?? 0) / totalNumPlayers) *
                  100
                ).toFixed(0)}
                %
              </Text>
              <Text c="dimmed" size='xs'><Trans>of players</Trans></Text>
            </Stack>
          </Grid.Col>
        </Grid>
      </UnstyledButton>
      <Sheet title={t`${badge.name} Badge Holders`} {...badgeSheet.props}>
        <PlayerList players={playersForList} />
      </Sheet>
      {!isLastRow && <Divider />}
    </Box>
  );
};
