import { useState, useMemo, useCallback, memo, useRef, useEffect, useDeferredValue } from "react";
import {
  Text,
  TextInput,
  Stack,
  Group,
  Box,
  ThemeIcon,
  Container,
  Title,
  Divider,
  UnstyledButton,
  Popover,
  ActionIcon,
  ScrollArea,
} from "@mantine/core";
import {
  MagnifyingGlassIcon,
  CaretUpIcon,
  CaretDownIcon,
  ChartBarIcon,
  InfoIcon,
} from "@phosphor-icons/react";
import { PlayerStats } from "../types";
import PlayerAvatar from "@/components/player-avatar";
import InfiniteScroll from "@/components/infinite-scroll";
import { useNavigate } from "@tanstack/react-router";
import { useAllPlayerStats } from "../queries";
import { PlayerListItemSkeleton } from "./player-stats-table-skeleton";
import { Trans, useLingui } from "@lingui/react/macro";

type SortKey = keyof PlayerStats | "mmr";
type SortDirection = "asc" | "desc";

interface SortConfig {
  key: SortKey;
  direction: SortDirection;
}

interface PlayerListItemProps {
  stat: PlayerStats;
  onPlayerClick: (playerId: string) => void;
  mmr: number;
  onRegisterViewport: (viewport: HTMLDivElement) => void;
  onUnregisterViewport: (viewport: HTMLDivElement) => void;
}

interface StatCellProps {
  label: string;
  value: string | number;
}

const StatCell = memo(({ label, value }: StatCellProps) => (
  <Stack justify="center" gap={0} style={{ textAlign: 'center', flexShrink: 0 }}>
    <Text size="xs" c="dimmed" fw={700}>
      {label}
    </Text>
    <Text size="xs" c="dimmed">
      {value}
    </Text>
  </Stack>
));

const PlayerListItem = memo(({ stat, onPlayerClick, mmr, onRegisterViewport, onUnregisterViewport }: PlayerListItemProps) => {
  const { t } = useLingui();
  const viewportRef = useRef<HTMLDivElement>(null);

  const avg_cups_against = useMemo(() => stat.total_cups_against / stat.matches || 0, [stat.total_cups_against, stat.matches]);

  useEffect(() => {
    if (viewportRef.current) {
      onRegisterViewport(viewportRef.current);
      return () => {
        if (viewportRef.current) {
          onUnregisterViewport(viewportRef.current);
        }
      };
    }
  }, [onRegisterViewport, onUnregisterViewport]);

  return (
    <>
      <UnstyledButton
        w="100%"
        p="md"
        onClick={() => onPlayerClick(stat.id)}
        style={{
          borderRadius: 0,
          transition: "background-color 0.15s ease",
        }}
        styles={{
          root: {
            '&:hover': {
              backgroundColor: 'var(--mantine-color-gray-0)',
            },
          },
        }}
      >
        <Group p={0} gap="sm" align="center" w="100%" wrap="nowrap" style={{ overflow: 'hidden' }}>
          <PlayerAvatar name={stat.player_name} size={40} style={{ flexShrink: 0 }} disableFullscreen />
          <Stack gap={2} style={{ flexGrow: 1, overflow: 'hidden', minWidth: 0 }}>
            <Group gap='xs'>
              <Text size="sm" fw={600}>
                {stat.player_name}
              </Text>
              <Text size="xs" c="dimmed" ta="right">
                {stat.matches}
                <Text span fw={800}><Trans>M</Trans></Text>
              </Text>
              <Text size="xs" c="dimmed" ta="right">
                {stat.tournaments}
                <Text span fw={800}><Trans>T</Trans></Text>
              </Text>
            </Group>

            <ScrollArea
              viewportRef={viewportRef}
              type="never"
              styles={{
                viewport: {
                  WebkitOverflowScrolling: 'touch',
                  scrollBehavior: 'auto',
                  willChange: 'scroll-position',
                  transform: 'translateZ(0)',
                  backfaceVisibility: 'hidden',
                },
              }}
            >
              <Group gap='xs' wrap="nowrap">
                <StatCell label={t`MMR`} value={mmr.toFixed(1)} />
                <StatCell label={t`W`} value={stat.wins} />
                <StatCell label={t`L`} value={stat.losses} />
                <StatCell label={t`W%`} value={`${stat.win_percentage.toFixed(1)}%`} />
                <StatCell label={t`AWM`} value={stat.margin_of_victory?.toFixed(1) || 0} />
                <StatCell label={t`ALM`} value={stat.margin_of_loss?.toFixed(1) || 0} />
                <StatCell label={t`AC`} value={stat.avg_cups_per_match.toFixed(1)} />
                <StatCell label={t`ACA`} value={avg_cups_against?.toFixed(1) || 0} />
                <StatCell label={t`CF`} value={stat.total_cups_made} />
                <StatCell label={t`CA`} value={stat.total_cups_against} />
              </Group>
            </ScrollArea>
          </Stack>
        </Group>
      </UnstyledButton>
    </>
  );
});

interface PlayerStatsTableProps {
  viewType?: 'all' | 'mainline' | 'regional';
}

const calculateMMR = (stat: PlayerStats): number => {
  if (stat.matches === 0) return 0;

  const winScore = stat.win_percentage;
  const matchConfidence = Math.min(stat.matches / 15, 1);
  const avgCupsScore = Math.min(stat.avg_cups_per_match * 10, 100);
  const marginScore = stat.margin_of_victory
    ? Math.min(stat.margin_of_victory * 20, 50)
    : 0;
  const volumeBonus = Math.min(stat.matches * 0.5, 10);

  const baseMMR =
    winScore * 0.5 +
    avgCupsScore * 0.25 +
    marginScore * 0.15 +
    volumeBonus * 0.1;

  const finalMMR = baseMMR * matchConfidence;
  return Math.round(finalMMR * 10) / 10;
};

const PlayerStatsTable = ({ viewType = 'all' }: PlayerStatsTableProps) => {
  const { t } = useLingui();
  const { data: playerStats } = useAllPlayerStats(viewType);
  const navigate = useNavigate();
  const [search, setSearch] = useState("");
  const deferredSearch = useDeferredValue(search);
  const [sortConfig, setSortConfig] = useState<SortConfig>({
    key: "mmr" as SortKey,
    direction: "desc",
  });

  const viewportsRef = useRef<Set<HTMLDivElement>>(new Set());
  const scrollHandlersRef = useRef<Map<HTMLDivElement, (e: Event) => void>>(new Map());
  const scrollLeaderRef = useRef<HTMLDivElement | null>(null);
  const scrollTimeoutRef = useRef<number | null>(null);
  const lastScrollLeftRef = useRef(0);

  const handleRegisterViewport = useCallback((viewport: HTMLDivElement) => {
    viewportsRef.current.add(viewport);

    if (lastScrollLeftRef.current > 0) {
      viewport.scrollLeft = lastScrollLeftRef.current;
    }

    const handleScrollStart = () => {
      scrollLeaderRef.current = viewport;
    };

    const handleScroll = (e: Event) => {
      const target = e.target as HTMLDivElement;

      if (!scrollLeaderRef.current) {
        scrollLeaderRef.current = target;
      }

      if (scrollLeaderRef.current !== target) {
        return;
      }

      const scrollLeft = target.scrollLeft;
      lastScrollLeftRef.current = scrollLeft;

      viewportsRef.current.forEach((vp) => {
        if (vp !== target && Math.abs(vp.scrollLeft - scrollLeft) > 0.5) {
          vp.scrollLeft = scrollLeft;
        }
      });

      if (scrollTimeoutRef.current) {
        clearTimeout(scrollTimeoutRef.current);
      }
      scrollTimeoutRef.current = window.setTimeout(() => {
        scrollLeaderRef.current = null;
      }, 150);
    };

    viewport.addEventListener('touchstart', handleScrollStart, { passive: true });
    viewport.addEventListener('mousedown', handleScrollStart, { passive: true });
    viewport.addEventListener('scroll', handleScroll, { passive: true });

    scrollHandlersRef.current.set(viewport, handleScroll);
  }, []);

  const handleUnregisterViewport = useCallback((viewport: HTMLDivElement) => {
    viewportsRef.current.delete(viewport);

    const handler = scrollHandlersRef.current.get(viewport);
    if (handler) {
      viewport.removeEventListener('scroll', handler);
      viewport.removeEventListener('touchstart', handler);
      viewport.removeEventListener('mousedown', handler);
      scrollHandlersRef.current.delete(viewport);
    }
  }, []);

  const statsWithMMR = useMemo(() => {
    return playerStats.map((stat) => ({
      ...stat,
      mmr: calculateMMR(stat),
    }));
  }, [playerStats]);

  const filteredAndSortedStats = useMemo(() => {
    let filtered = statsWithMMR.filter((stat) =>
      stat.player_name.toLowerCase().includes(deferredSearch.toLowerCase())
    );

    return filtered.sort((a, b) => {
      let aValue: number | string;
      let bValue: number | string;

      if (sortConfig.key === "mmr") {
        aValue = a.mmr;
        bValue = b.mmr;
      } else {
        aValue = a[sortConfig.key];
        bValue = b[sortConfig.key];
      }

      if (typeof aValue === "number" && typeof bValue === "number") {
        return sortConfig.direction === "desc"
          ? bValue - aValue
          : aValue - bValue;
      }

      if (typeof aValue === "string" && typeof bValue === "string") {
        return sortConfig.direction === "desc"
          ? bValue.localeCompare(aValue)
          : aValue.localeCompare(bValue);
      }

      return 0;
    });
  }, [statsWithMMR, deferredSearch, sortConfig]);

  const handlePlayerClick = useCallback((playerId: string) => {
    navigate({ to: `/profile/${playerId}` });
  }, [navigate]);

  const handleSort = (key: SortKey) => {
    setSortConfig((prev) => ({
      key,
      direction: prev.key === key && prev.direction === "desc" ? "asc" : "desc",
    }));
  };

  const getSortIcon = (key: SortKey) => {
    if (sortConfig.key !== key) return null;
    return sortConfig.direction === "desc" ? (
      <CaretDownIcon size={14} />
    ) : (
      <CaretUpIcon size={14} />
    );
  };

  if (playerStats.length === 0) {
    return (
      <Stack align="center" gap="md" py="xl">
        <ThemeIcon size="xl" variant="light" radius="md">
          <ChartBarIcon size={32} />
        </ThemeIcon>
        <Title order={3} c="dimmed">
          <Trans>No Stats Available</Trans>
        </Title>
      </Stack>
    );
  }

  return (
    <Container size="100%" px={0}>
      <Stack gap="xs">
        <Text px="md" size="10px" lh={0} c="dimmed">
          <Trans>Showing {filteredAndSortedStats.length} of {playerStats.length} players</Trans>
        </Text>
        <TextInput
          placeholder={t`Search players`}
          value={search}
          onChange={(e) => setSearch(e.currentTarget.value)}
          leftSection={<MagnifyingGlassIcon size={16} />}
          size="md"
          px="md"
        />

        <Group px="md" justify="space-between" align="center">
          <Group gap="xs" w="100%">
            <div></div>
            <Text ml='auto' size="xs" c="dimmed"><Trans>Sort:</Trans></Text>
            <UnstyledButton
              onClick={() => handleSort("mmr")}
              style={{ display: "flex", alignItems: "center", gap: 4 }}
            >
              <Text size="xs" fw={sortConfig.key === "mmr" ? 600 : 400} c={sortConfig.key === "mmr" ? "var(--mantine-color-text)" : "dimmed"}>
                <Trans>MMR</Trans>
              </Text>
              {getSortIcon("mmr")}
            </UnstyledButton>
            <Text size="xs" c="dimmed">•</Text>
            <UnstyledButton
              onClick={() => handleSort("wins")}
              style={{ display: "flex", alignItems: "center", gap: 4 }}
            >
              <Text size="xs" fw={sortConfig.key === "wins" ? 600 : 400} c={sortConfig.key === "wins" ? "var(--mantine-color-text)" : "dimmed"}>
                <Trans>Wins</Trans>
              </Text>
              {getSortIcon("wins")}
            </UnstyledButton>
            <Text size="xs" c="dimmed">•</Text>
            <UnstyledButton
              onClick={() => handleSort("matches")}
              style={{ display: "flex", alignItems: "center", gap: 4 }}
            >
              <Text size="xs" fw={sortConfig.key === "matches" ? 600 : 400} c={sortConfig.key === "matches" ? "var(--mantine-color-text)" : "dimmed"}>
                <Trans>Matches</Trans>
              </Text>
              {getSortIcon("matches")}
            </UnstyledButton>
            <Popover position="bottom-end" withArrow shadow="md">
              <Popover.Target>
                <ActionIcon variant="subtle" size="sm" aria-label={t`Stat abbreviations and MMR info`}>
                  <InfoIcon size={14} />
                </ActionIcon>
              </Popover.Target>
              <Popover.Dropdown>
                <Box maw={280}>
                  <Text size="sm" fw={500} mb="xs">
                    <Trans>Stat Abbreviations:</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>M:</strong> Matches</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>T:</strong> Tournaments</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>MMR:</strong> Matchmaking Rating</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>W:</strong> Wins</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>L:</strong> Losses</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>W%:</strong> Win Percentage</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>AWM:</strong> Average Win Margin</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>ALM:</strong> Average Loss Margin</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>AC:</strong> Average Cups Per Match</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>ACA:</strong> Average Cups Against</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>CF:</strong> Cups For</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• <strong>CA:</strong> Cups Against</Trans>
                  </Text>

                  <Divider my="sm" />

                  <Text size="sm" fw={500} mb="xs">
                    <Trans>MMR Calculation:</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• Win Rate (50%)</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• Average Cups/Match (25%)</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• Average Win Margin (15%)</Trans>
                  </Text>
                  <Text size="xs" mb={2}>
                    <Trans>• Match Volume Bonus (10%)</Trans>
                  </Text>
                  <Text size="xs" mt="xs" c="dimmed">
                    <Trans>* Confidence penalty applied for players with &lt;15 matches</Trans>
                  </Text>
                  <Text size="xs" mt="xs" c="dimmed">
                    <Trans>** Not an official rating</Trans>
                  </Text>
                </Box>
              </Popover.Dropdown>
            </Popover>
          </Group>
        </Group>

        <Stack gap={0}>
          <InfiniteScroll
            items={filteredAndSortedStats}
            batchSize={25}
            renderItem={(stat, index) => (
              <Box key={stat.id}>
                {index > 0 && <Divider />}
                <PlayerListItem
                  stat={stat}
                  onPlayerClick={handlePlayerClick}
                  mmr={stat.mmr}
                  onRegisterViewport={handleRegisterViewport}
                  onUnregisterViewport={handleUnregisterViewport}
                />
              </Box>
            )}
            loader={
              <>
                <Divider />
                <PlayerListItemSkeleton />
                <Divider />
                <PlayerListItemSkeleton />
              </>
            }
          />
        </Stack>

        {filteredAndSortedStats.length === 0 && search && (
          <Text ta="center" c="dimmed" py="xl">
            <Trans>No players found matching "{search}"</Trans>
          </Text>
        )}
      </Stack>
    </Container>
  );
};

export default PlayerStatsTable;
