import {
  Group,
  Button,
  Text,
  TextProps,
  Stack,
  ScrollArea,
  Paper,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { useState, useRef, useEffect, useCallback } from "react";
import { AnimatePresence, motion, useReducedMotion } from "framer-motion";
import { useLingui } from "@lingui/react/macro";
import Sheet from "@/components/sheet/sheet";
import PlayerList from "@/features/players/components/player-list";
import EmojiPicker from "./emoji-picker";
import { useMatchReactions, useToggleMatchReaction } from "../queries";
import { useAuth } from "@/contexts/auth-context";
import { Reaction } from "@/features/matches/server";
import classes from "./emoji-bar.module.css";

interface EmojiBarProps {
  matchId: string;
  onReactionPress?: (emoji: string) => void;
}

const EASE: [number, number, number, number] = [0.32, 0.72, 0, 1];

interface TickingCountProps extends TextProps {
  value: number;
}

const TickingCount = ({ value, ...textProps }: TickingCountProps) => {
  const mountedRef = useRef(false);

  useEffect(() => {
    mountedRef.current = true;
  }, []);

  return (
    <Text component="span" {...textProps}>
      <span
        key={value}
        className={
          mountedRef.current
            ? `${classes.count} ${classes.countTick}`
            : classes.count
        }
      >
        {value}
      </span>
    </Text>
  );
};

const EmojiBar = ({
  matchId,
  onReactionPress,
}: EmojiBarProps) => {
  const { user } = useAuth();
  const { t } = useLingui();
  const { data: reactions } = useMatchReactions(matchId);
  const toggleReaction = useToggleMatchReaction(matchId, user);
  const reduceMotion = useReducedMotion();

  const [opened, { open, close }] = useDisclosure(false);
  const [selectedEmoji, setSelectedEmoji] = useState<string | null>(null);
  const longPressTimeout = useRef<NodeJS.Timeout | null>(null);

  const handleLongPressStart = (emoji: string) => {
    longPressTimeout.current = setTimeout(() => {
      setSelectedEmoji(emoji);
      open();
    }, 500);
  };

  const handleLongPressEnd = () => {
    if (longPressTimeout.current) {
      clearTimeout(longPressTimeout.current);
    }
  };

  const handleReactionClick = (emoji: string) => {
    handleLongPressEnd();
    if (onReactionPress) {
      onReactionPress(emoji);
    } else {
      toggleReaction.mutate({ data: { matchId, emoji } });
    }
  };

  const hasReacted = useCallback((reaction: Reaction) => {
    return reaction.players.map(p => p.id).includes(user?.id || "");
  }, [user?.id]);

  const userReactions = reactions?.filter(r => hasReacted(r)).map(r => r.emoji) || [];

  if (!reactions) return;

  const sortedReactions = [...reactions].sort((a, b) => b.count - a.count);

  const visibleReactions = sortedReactions.slice(0, 3);
  const groupedReactions = sortedReactions.slice(3);

  const hasGrouped = groupedReactions.length > 0;
  const groupedCount = groupedReactions.reduce((sum, r) => sum + r.count, 0);
  const userHasReactedToGrouped = groupedReactions.some(r => hasReacted(r));

  const chipMotionProps = {
    layout: !reduceMotion,
    initial: reduceMotion ? { opacity: 1, scale: 1 } : { opacity: 0, scale: 0.8 },
    animate: { opacity: 1, scale: 1 },
    exit: reduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.8 },
    transition: { duration: reduceMotion ? 0 : 0.18, ease: EASE },
  };

  return (
    <>
      <Group gap="xs" wrap="wrap" justify="space-between">
        <Group gap="xs" wrap="wrap">
          <AnimatePresence initial={false} mode="popLayout">
            {visibleReactions.map((reaction) => (
              <motion.div key={reaction.emoji} {...chipMotionProps}>
                <Button
                  variant={"light"}
                  bd={hasReacted(reaction) ? "1px solid var(--mantine-primary-color-filled)" : undefined}
                  size="compact-xs"
                  radius="xl"
                  onMouseDown={() => handleLongPressStart(reaction.emoji)}
                  onMouseUp={handleLongPressEnd}
                  onMouseLeave={handleLongPressEnd}
                  onTouchStart={() => handleLongPressStart(reaction.emoji)}
                  onTouchEnd={handleLongPressEnd}
                  onClick={() => handleReactionClick(reaction.emoji)}
                  style={{
                    userSelect: "none",
                    WebkitUserSelect: "none",
                    MozUserSelect: "none",
                    msUserSelect: "none",
                  }}
                >
                  <Group gap={2} align="center">
                    <Text size="xs" style={{ lineHeight: 1 }}>
                      {reaction.emoji}
                    </Text>
                    <TickingCount size="xs" fw={600} value={reaction.count} />
                  </Group>
                </Button>
              </motion.div>
            ))}

            {hasGrouped && (
              <motion.div key="grouped-reactions" {...chipMotionProps}>
                <Button
                  variant={"light"}
                  bd={userHasReactedToGrouped ? "1px solid var(--mantine-primary-color-filled)" : undefined}
                  size="compact-xs"
                  radius="xl"
                  onMouseDown={() => handleLongPressStart(groupedReactions[0]?.emoji || "")}
                  onMouseUp={handleLongPressEnd}
                  onMouseLeave={handleLongPressEnd}
                  onTouchStart={() => handleLongPressStart(groupedReactions[0]?.emoji || "")}
                  onTouchEnd={handleLongPressEnd}
                  onClick={() => {
                    setSelectedEmoji(groupedReactions[0]?.emoji || "");
                    open();
                  }}
                  style={{
                    userSelect: "none",
                    WebkitUserSelect: "none",
                    MozUserSelect: "none",
                    msUserSelect: "none",
                    position: "relative",
                  }}
                >
                  <Group gap={2} align="center">
                    <div style={{
                      display: "flex",
                      gap: "1px",
                      alignItems: "center",
                      fontSize: "10px",
                      lineHeight: 1
                    }}>
                      {groupedReactions.slice(0, 2).map((reaction) => (
                        <span key={reaction.emoji}>{reaction.emoji}</span>
                      ))}
                      {groupedReactions.length > 2 && (
                        <Text size="8px" fw={600} c="dimmed">
                          +{groupedReactions.length - 2}
                        </Text>
                      )}
                    </div>
                    <TickingCount size="xs" fw={600} value={groupedCount} />
                  </Group>
                </Button>
              </motion.div>
            )}
          </AnimatePresence>
        </Group>
        <EmojiPicker
          onSelect={onReactionPress || ((emoji) => toggleReaction.mutate({ data: { matchId, emoji } }))}
          userReactions={userReactions}
        />
      </Group>

      <Sheet title={t`Reactions`} opened={opened} onChange={() => close()}>
        <Stack gap="md">
          <ScrollArea w="100%" offsetScrollbars>
            <Group gap="xs" wrap="nowrap" px="xs">
              {sortedReactions.map((reaction) => (
                <Button
                  key={reaction.emoji}
                  variant={selectedEmoji === reaction.emoji ? "filled" : "light"}
                  color="gray"
                  size="compact-sm"
                  radius="xl"
                  onClick={() => setSelectedEmoji(reaction.emoji)}
                  style={{ flexShrink: 0 }}
                >
                  <Group gap={4} align="center">
                    <Text size="sm">{reaction.emoji}</Text>
                    <TickingCount size="xs" fw={600} value={reaction.count} />
                  </Group>
                </Button>
              ))}
            </Group>
          </ScrollArea>

          {selectedEmoji && (
            <Paper p="md" withBorder radius="md">
              <Group gap="sm" mb="md">
                <Text size="2xl">{selectedEmoji}</Text>
                <div>
                  <Text size="lg" fw={600}>
                    {sortedReactions.find(r => r.emoji === selectedEmoji)?.count || 0}
                  </Text>
                </div>
              </Group>
              <PlayerList players={sortedReactions.find(r => r.emoji === selectedEmoji)?.players || []} />
            </Paper>
          )}
        </Stack>
      </Sheet>
    </>
  );
};

export default EmojiBar;
