import { useState, useEffect, useCallback, useRef } from 'react';
import { motion } from 'framer-motion';
import { useSettings } from '@/contexts/SettingsContext';
import { useAchievements } from '@/contexts/AchievementsContext';
import { Link } from 'react-router-dom';
import GlitchCrash from '@/components/GlitchCrash';
import { Maximize2, Minimize2 } from 'lucide-react';
import { useBrowserFullscreen } from '@/hooks/useGameDimensions';
import { MobileControlsDock, MobileControlsSpacer } from '@/components/MobileControlsDock';
import { useSwipeControls } from '@/hooks/useSwipeControls';
import GameTouchButton from '@/components/GameTouchButton';

const GRID_WIDTH = 21;
const GRID_HEIGHT = 21;
const TICK_SPEED = 180;
const POWER_DURATION = 8000;
const MAX_SCORE = 4294967296;
const HIGHSCORE_KEY = 'pacman-highscore';

type Direction = 'up' | 'down' | 'left' | 'right';
type Position = { x: number; y: number };

const MAZE_TEMPLATE = [
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  [1,3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,3,1],
  [1,0,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,1,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,1,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1,0,1],
  [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
  [1,1,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,1],
  [1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1],
  [1,1,1,1,0,1,0,1,1,0,0,0,1,1,0,1,0,1,1,1,1],
  [2,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,2],
  [1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1],
  [1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1],
  [1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1],
  [1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1],
  [1,0,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,1,0,1],
  [1,3,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,3,1],
  [1,1,0,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,0,1,1],
  [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
  [1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
];

const Pacman = () => {
  const { playSound, mobileControlMode } = useSettings();
  const { checkGameScoreAchievements, unlockMaxScore } = useAchievements();

  // Game mode selection
  const [gameMode, setGameMode] = useState<'1p' | '2p'>('1p');
  const [showModeSelection, setShowModeSelection] = useState(true);

  // Player 1 (always active)
  const [pacman, setPacman] = useState<Position>({ x: 10, y: 15 });
  const [direction, setDirection] = useState<Direction>('right');
  const [nextDirection, setNextDirection] = useState<Direction>('right');
  const [mouthOpen, setMouthOpen] = useState(true);
  const [lives, setLives] = useState(3);

  // Player 2 (for 2P mode)
  const [pacman2, setPacman2] = useState<Position>({ x: 10, y: 15 });
  const [direction2, setDirection2] = useState<Direction>('right');
  const [nextDirection2, setNextDirection2] = useState<Direction>('right');
  const [mouthOpen2, setMouthOpen2] = useState(true);
  const [lives2, setLives2] = useState(3);
  const [player1Eliminated, setPlayer1Eliminated] = useState(false);
  const [player2Eliminated, setPlayer2Eliminated] = useState(false);
  const [showEliminationPrompt, setShowEliminationPrompt] = useState(false);
  const [ghosts, setGhosts] = useState<{ pos: Position; dir: Direction; eaten: boolean }[]>([
    { pos: { x: 9, y: 9 }, dir: 'left', eaten: false },
    { pos: { x: 10, y: 9 }, dir: 'up', eaten: false },
    { pos: { x: 11, y: 9 }, dir: 'right', eaten: false },
  ]);
   const [dots, setDots] = useState<Set<string>>(new Set());
   const [powerPellets, setPowerPellets] = useState<Set<string>>(new Set());
   const [isPowered, setIsPowered] = useState(false);
   const [score, setScore] = useState(0);
   const [score2, setScore2] = useState(0);
   const [highScore, setHighScore] = useState(0);
  const [gameOver, setGameOver] = useState(false);
  const [gameComplete, setGameComplete] = useState(false);
  const [gameStarted, setGameStarted] = useState(false);
  const [isPaused, setIsPaused] = useState(false);
  const [showGlitchCrash, setShowGlitchCrash] = useState(false);
  const [level, setLevel] = useState(1);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const gameRef = useRef<HTMLDivElement>(null);
  const powerTimerRef = useRef<NodeJS.Timeout | null>(null);

  const { enterFullscreen, exitFullscreen } = useBrowserFullscreen();

  const getCellSize = useCallback(() => {
    if (typeof window === 'undefined') return 24;
    const isMobile = window.innerWidth < 768;
    if (isMobile) {
      const maxWidth = window.innerWidth - 40;
      // Reserve space for header + fixed controls dock on mobile
      const maxHeight = window.innerHeight - 420;
      return Math.min(Math.floor(maxWidth / GRID_WIDTH), Math.floor(maxHeight / GRID_HEIGHT), 18);
    }
    return isFullscreen ? 30 : 24;
  }, [isFullscreen]);

  const [cellSize, setCellSize] = useState(getCellSize);
  const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;

  // Swipe controls for mobile
  const { getSwipeHandlers } = useSwipeControls({
    onSwipe: (dir) => {
      if (gameMode === '1p' && gameStarted && !gameOver && !gameComplete && !isPaused) {
        setNextDirection(dir as Direction);
      }
    },
    onTap: () => {
      if (gameStarted && !gameOver && !gameComplete) setIsPaused(p => !p);
    },
    enabled: isMobile && gameStarted && !gameOver && !gameComplete && mobileControlMode === 'swipe',
  });

  const useButtonControls = isMobile && mobileControlMode === 'buttons';

  useEffect(() => {
    const handleResize = () => setCellSize(getCellSize());
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, [getCellSize]);

  useEffect(() => { setCellSize(getCellSize()); }, [isFullscreen, getCellSize]);

  useEffect(() => {
    if (gameStarted && isMobile && !isFullscreen) { setIsFullscreen(true); enterFullscreen(); }
  }, [gameStarted, isMobile, isFullscreen, enterFullscreen]);

  const toggleFullscreen = async () => {
    if (!isFullscreen) { setIsFullscreen(true); await enterFullscreen(); }
    else { setIsFullscreen(false); await exitFullscreen(); }
    playSound('click');
  };

  useEffect(() => {
    const handleEscape = (e: KeyboardEvent) => { if (e.key === 'Escape' && isFullscreen) { setIsFullscreen(false); exitFullscreen(); } };
    window.addEventListener('keydown', handleEscape);
    return () => window.removeEventListener('keydown', handleEscape);
  }, [isFullscreen, exitFullscreen]);

  useEffect(() => {
    const saved = localStorage.getItem(HIGHSCORE_KEY);
    if (saved) setHighScore(Math.min(parseInt(saved, 10), MAX_SCORE));
  }, []);

  // Check score achievements
  useEffect(() => {
    if (score > 0) {
      checkGameScoreAchievements('pacman', score);
      if (score >= MAX_SCORE) unlockMaxScore();
    }
  }, [score, checkGameScoreAchievements, unlockMaxScore]);

  const initDots = useCallback(() => {
    const newDots = new Set<string>();
    const newPowerPellets = new Set<string>();
    for (let y = 0; y < GRID_HEIGHT; y++) {
      for (let x = 0; x < GRID_WIDTH; x++) {
        if (MAZE_TEMPLATE[y][x] === 0) newDots.add(`${x},${y}`);
        else if (MAZE_TEMPLATE[y][x] === 3) newPowerPellets.add(`${x},${y}`);
      }
    }
    newDots.delete('10,15'); newDots.delete('9,9'); newDots.delete('10,9'); newDots.delete('11,9');
    return { dots: newDots, powerPellets: newPowerPellets };
  }, []);

  const canMove = (pos: Position, dir: Direction): boolean => {
    let newX = pos.x, newY = pos.y;
    switch (dir) { case 'up': newY--; break; case 'down': newY++; break; case 'left': newX--; break; case 'right': newX++; break; }
    if (newX < 0) return MAZE_TEMPLATE[newY]?.[GRID_WIDTH - 1] !== 1;
    if (newX >= GRID_WIDTH) return MAZE_TEMPLATE[newY]?.[0] !== 1;
    if (newY < 0 || newY >= GRID_HEIGHT) return false;
    return MAZE_TEMPLATE[newY][newX] !== 1;
  };

  const moveEntity = (pos: Position, dir: Direction): Position => {
    let newX = pos.x, newY = pos.y;
    switch (dir) { case 'up': newY--; break; case 'down': newY++; break; case 'left': newX--; break; case 'right': newX++; break; }
    if (newX < 0) newX = GRID_WIDTH - 1;
    if (newX >= GRID_WIDTH) newX = 0;
    return { x: newX, y: newY };
  };

  const activatePowerMode = () => {
    if (powerTimerRef.current) clearTimeout(powerTimerRef.current);
    setIsPowered(true);
    powerTimerRef.current = setTimeout(() => { setIsPowered(false); setGhosts(prev => prev.map(g => ({ ...g, eaten: false }))); }, POWER_DURATION);
  };

  const startGame = () => {
    if (powerTimerRef.current) clearTimeout(powerTimerRef.current);
    setPacman({ x: 10, y: 15 }); setDirection('right'); setNextDirection('right'); setMouthOpen(true);
    setPacman2({ x: 10, y: 15 }); setDirection2('right'); setNextDirection2('right'); setMouthOpen2(true);
    setLives(3); setLives2(3);
    setGhosts([{ pos: { x: 9, y: 9 }, dir: 'left', eaten: false }, { pos: { x: 10, y: 9 }, dir: 'up', eaten: false }, { pos: { x: 11, y: 9 }, dir: 'right', eaten: false }]);
    const { dots: newDots, powerPellets: newPowerPellets } = initDots();
    setDots(newDots); setPowerPellets(newPowerPellets); setIsPowered(false); setScore(0); setScore2(0); setLevel(1);
    setGameOver(false); setGameComplete(false); setIsPaused(false); setGameStarted(true); setShowModeSelection(false);
    setPlayer1Eliminated(false); setPlayer2Eliminated(false); setShowEliminationPrompt(false);
    playSound('success'); gameRef.current?.focus();
  };

  const continueIn1PMode = () => {
    setGameMode('1p');
    setShowEliminationPrompt(false);
    setIsPaused(false);
    playSound('success');
  };

  useEffect(() => { return () => { if (powerTimerRef.current) clearTimeout(powerTimerRef.current); }; }, []);

  useEffect(() => {
    if (!gameStarted || gameOver || gameComplete || isPaused) return;
    const interval = setInterval(() => {
      // Handle both players
      const handlePlayerMovement = (
        player: Position, playerDir: Direction, playerNextDir: Direction,
        setPlayerDir: (dir: Direction) => void, setPlayer: (pos: Position) => void,
        setPlayerScore: (fn: (prev: number) => number) => void,
        setPlayerMouth?: (fn: (prev: boolean) => boolean) => void
      ) => {
        // Animate mouth every tick for smoother appearance
        if (setPlayerMouth) setPlayerMouth(prev => !prev);

        if (canMove(player, playerNextDir)) setPlayerDir(playerNextDir);
        const actualDir = canMove(player, playerNextDir) ? playerNextDir : playerDir;

        if (canMove(player, actualDir)) {
          const newPos = moveEntity(player, actualDir);

          // Check for ghosts at target position BEFORE moving
          let ghostAtTarget = null;
          let ghostIndex = -1;
          for (let i = 0; i < ghosts.length; i++) {
            if (ghosts[i].pos.x === newPos.x && ghosts[i].pos.y === newPos.y) {
              ghostAtTarget = ghosts[i];
              ghostIndex = i;
              break;
            }
          }

          if (ghostAtTarget) {
            // There's a ghost at the target position
            if (isPowered && !ghostAtTarget.eaten) {
              // Eat the ghost - move to position and score
              setPlayer(newPos);
              setGhosts(prev => prev.map((g, idx) => idx === ghostIndex ? { ...g, eaten: true, pos: { x: 10, y: 9 } } : g));
              setPlayerScore(prev => {
                const ns = Math.min(prev + 200, MAX_SCORE);
                if (ns >= MAX_SCORE) setShowGlitchCrash(true);
                if (ns > highScore) { setHighScore(ns); localStorage.setItem(HIGHSCORE_KEY, ns.toString()); }
                return ns;
              });
              playSound('success');
            } else if (!ghostAtTarget.eaten) {
              // Hit by ghost - lose life without moving
              const isPlayer1 = player === pacman;
              const currentLives = isPlayer1 ? lives : lives2;
              const setLivesFunc = isPlayer1 ? setLives : setLives2;

              const newLives = currentLives - 1;
              setLivesFunc(newLives);

              if (newLives > 0) {
                // Respawn at start
                setPlayer({ x: 10, y: 15 });
                playSound('error');
              } else {
                // Player eliminated
                if (isPlayer1) {
                  setPlayer1Eliminated(true);
                  setPacman({ x: -1, y: -1 });
                } else {
                  setPlayer2Eliminated(true);
                  setPacman2({ x: -1, y: -1 });
                }
                playSound('error');

                if (gameMode === '2p' && ((isPlayer1 && !player2Eliminated) || (!isPlayer1 && !player1Eliminated))) {
                  setShowEliminationPrompt(true);
                  setIsPaused(true);
                } else {
                  setGameOver(true);
                }
              }
            }
          } else {
            // No ghost at target, safe to move
            setPlayer(newPos);

            const posKey = `${newPos.x},${newPos.y}`;
            if (powerPellets.has(posKey)) {
              setPowerPellets(prev => { const np = new Set(prev); np.delete(posKey); return np; });
              activatePowerMode();
              setPlayerScore(prev => {
                const ns = Math.min(prev + 50, MAX_SCORE);
                if (ns >= MAX_SCORE) setShowGlitchCrash(true);
                if (ns > highScore) { setHighScore(ns); localStorage.setItem(HIGHSCORE_KEY, ns.toString()); }
                return ns;
              });
              playSound('success');
            } else if (dots.has(posKey)) {
              setDots(prev => { const nd = new Set(prev); nd.delete(posKey); return nd; });
              setPlayerScore(prev => {
                const ns = Math.min(prev + 10, MAX_SCORE);
                if (ns >= MAX_SCORE) setShowGlitchCrash(true);
                if (ns > highScore) { setHighScore(ns); localStorage.setItem(HIGHSCORE_KEY, ns.toString()); }
                return ns;
              });
              playSound('hover');
            }
          }
        }
      };

      // Player 1 (only if not eliminated)
      if (!player1Eliminated) {
        handlePlayerMovement(pacman, direction, nextDirection, setDirection, setPacman, setScore, setMouthOpen);

        // Check collisions immediately after movement
        for (let i = 0; i < ghosts.length; i++) {
          const ghost = ghosts[i];
          if (ghost.pos.x === pacman.x && ghost.pos.y === pacman.y) {
            if (isPowered && !ghost.eaten) {
              setGhosts(prev => prev.map((g, idx) => idx === i ? { ...g, eaten: true, pos: { x: 10, y: 9 } } : g));
              setScore(prev => {
                const ns = Math.min(prev + 200, MAX_SCORE);
                if (ns >= MAX_SCORE) setShowGlitchCrash(true);
                if (ns > highScore) { setHighScore(ns); localStorage.setItem(HIGHSCORE_KEY, ns.toString()); }
                return ns;
              });
              playSound('success');
            } else if (!ghost.eaten) {
              // Player 1 dies
              const newLives = lives - 1;
              setLives(newLives);
              if (newLives > 0) {
                setPacman({ x: 10, y: 15 });
                playSound('error');
              } else {
                setPlayer1Eliminated(true);
                setPacman({ x: -1, y: -1 });
                playSound('error');
                if (gameMode === '2p' && !player2Eliminated) {
                  setShowEliminationPrompt(true);
                  setIsPaused(true);
                } else {
                  setGameOver(true);
                }
              }
            }
          }
        }
      }

      // Player 2 (only in 2P mode and not eliminated)
      if (gameMode === '2p' && !player2Eliminated) {
        handlePlayerMovement(pacman2, direction2, nextDirection2, setDirection2, setPacman2, setScore2, setMouthOpen2);
      }

      setGhosts(prev => prev.map(ghost => {
        if (ghost.eaten) return ghost;
        const directions: Direction[] = ['up', 'down', 'left', 'right'];
        const opposite: Record<Direction, Direction> = { up: 'down', down: 'up', left: 'right', right: 'left' };
        const validDirs = directions.filter(d => d !== opposite[ghost.dir] && canMove(ghost.pos, d));
        if (validDirs.length === 0) {
          const anyValid = directions.filter(d => canMove(ghost.pos, d));
          if (anyValid.length === 0) return ghost;
          const dir = anyValid[Math.floor(Math.random() * anyValid.length)];
          return { ...ghost, pos: moveEntity(ghost.pos, dir), dir };
        }
        const dx = pacman.x - ghost.pos.x, dy = pacman.y - ghost.pos.y;
        let preferredDirs: Direction[] = [];
        if (isPowered) { preferredDirs = Math.abs(dx) > Math.abs(dy) ? (dx > 0 ? ['left', 'up', 'down', 'right'] : ['right', 'down', 'up', 'left']) : (dy > 0 ? ['up', 'left', 'right', 'down'] : ['down', 'right', 'left', 'up']); }
        else { preferredDirs = Math.abs(dx) > Math.abs(dy) ? (dx > 0 ? ['right', 'down', 'up', 'left'] : ['left', 'up', 'down', 'right']) : (dy > 0 ? ['down', 'right', 'left', 'up'] : ['up', 'left', 'right', 'down']); }
        if (Math.random() < 0.6) { for (const dir of preferredDirs) { if (validDirs.includes(dir)) return { ...ghost, pos: moveEntity(ghost.pos, dir), dir }; } }
        const dir = validDirs[Math.floor(Math.random() * validDirs.length)];
        return { ...ghost, pos: moveEntity(ghost.pos, dir), dir };
      }));

      // Now check for collisions after all movement is complete
      // Check Player 1 collisions (from both player movement and ghost movement)
      if (!player1Eliminated) {
        setGhosts(currentGhosts => {
          for (let i = 0; i < currentGhosts.length; i++) {
            const ghost = currentGhosts[i];
            if (ghost.pos.x === pacman.x && ghost.pos.y === pacman.y) {
              if (isPowered && !ghost.eaten) {
                // Player eats ghost
                setScore(prev => {
                  const ns = Math.min(prev + 200, MAX_SCORE);
                  if (ns >= MAX_SCORE) setShowGlitchCrash(true);
                  if (ns > highScore) { setHighScore(ns); localStorage.setItem(HIGHSCORE_KEY, ns.toString()); }
                  return ns;
                });
                playSound('success');
                return currentGhosts.map((g, idx) => idx === i ? { ...g, eaten: true, pos: { x: 10, y: 9 } } : g);
              } else if (!ghost.eaten) {
                // Ghost kills player
                const newLives = lives - 1;
                setLives(newLives);
                if (newLives > 0) {
                  setPacman({ x: 10, y: 15 });
                  playSound('error');
                } else {
                  setPlayer1Eliminated(true);
                  setPacman({ x: -1, y: -1 });
                  playSound('error');
                  if (gameMode === '2p' && !player2Eliminated) {
                    setShowEliminationPrompt(true);
                    setIsPaused(true);
                  } else {
                    setGameOver(true);
                  }
                }
              }
            }
          }
          return currentGhosts;
        });
      }

      // Check Player 2 collisions
      if (gameMode === '2p' && !player2Eliminated) {
        setGhosts(currentGhosts => {
          for (let i = 0; i < currentGhosts.length; i++) {
            const ghost = currentGhosts[i];
            if (ghost.pos.x === pacman2.x && ghost.pos.y === pacman2.y) {
              if (isPowered && !ghost.eaten) {
                // Player eats ghost
                setScore2(prev => {
                  const ns = Math.min(prev + 200, MAX_SCORE);
                  if (ns >= MAX_SCORE) setShowGlitchCrash(true);
                  if (ns > highScore) { setHighScore(ns); localStorage.setItem(HIGHSCORE_KEY, ns.toString()); }
                  return ns;
                });
                playSound('success');
                return currentGhosts.map((g, idx) => idx === i ? { ...g, eaten: true, pos: { x: 10, y: 9 } } : g);
              } else if (!ghost.eaten) {
                // Ghost kills player
                const newLives = lives2 - 1;
                setLives2(newLives);
                if (newLives > 0) {
                  setPacman2({ x: 10, y: 15 });
                  playSound('error');
                } else {
                  setPlayer2Eliminated(true);
                  setPacman2({ x: -1, y: -1 });
                  playSound('error');
                  if (!player1Eliminated) {
                    setShowEliminationPrompt(true);
                    setIsPaused(true);
                  } else {
                    setGameOver(true);
                  }
                }
              }
            }
          }
          return currentGhosts;
        });
      }
    }, TICK_SPEED);
    return () => clearInterval(interval);
  }, [gameStarted, gameOver, gameComplete, isPaused, pacman, direction, nextDirection, pacman2, direction2, nextDirection2, dots, powerPellets, highScore, isPowered, playSound, gameMode, player1Eliminated, player2Eliminated]);



  // More responsive input - update direction immediately when pressed
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (!gameStarted || gameOver || gameComplete || isPaused) return;

      // Player 1 controls (WASD and Arrow keys) - immediate response
      switch (e.key) {
        // In 2P mode, P1 uses WASD only; in 1P mode, use both WASD and Arrows
        case 'ArrowUp':
          e.preventDefault();
          if (gameMode === '1p' && !player1Eliminated) setNextDirection('up');
          break;
        case 'ArrowDown':
          e.preventDefault();
          if (gameMode === '1p' && !player1Eliminated) setNextDirection('down');
          break;
        case 'ArrowLeft':
          e.preventDefault();
          if (gameMode === '1p' && !player1Eliminated) setNextDirection('left');
          break;
        case 'ArrowRight':
          e.preventDefault();
          if (gameMode === '1p' && !player1Eliminated) setNextDirection('right');
          break;
        case 'w': case 'W':
          e.preventDefault();
          if (!player1Eliminated) setNextDirection('up');
          break;
        case 's': case 'S':
          e.preventDefault();
          if (!player1Eliminated) setNextDirection('down');
          break;
        case 'a': case 'A':
          e.preventDefault();
          if (!player1Eliminated) setNextDirection('left');
          break;
        case 'd': case 'D':
          e.preventDefault();
          if (!player1Eliminated) setNextDirection('right');
          break;
      }

      // Player 2 controls (Arrow keys) - only in 2P mode
      // P1 uses WASD, P2 uses Arrow keys
      if (gameMode === '2p') {
        switch (e.key) {
          case 'ArrowUp':
            e.preventDefault();
            if (!player2Eliminated) setNextDirection2('up');
            break;
          case 'ArrowDown':
            e.preventDefault();
            if (!player2Eliminated) setNextDirection2('down');
            break;
          case 'ArrowLeft':
            e.preventDefault();
            if (!player2Eliminated) setNextDirection2('left');
            break;
          case 'ArrowRight':
            e.preventDefault();
            if (!player2Eliminated) setNextDirection2('right');
            break;
        }
      }
    };

    const handleKeyUp = (e: KeyboardEvent) => {
      if (!gameStarted || gameOver || gameComplete || isPaused) return;

      // Pause (works for both modes)
      if (e.key === 'p' || e.key === 'P') {
        e.preventDefault();
        if (!gameOver && !gameComplete) setIsPaused(prev => !prev);
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    window.addEventListener('keyup', handleKeyUp);
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
      window.removeEventListener('keyup', handleKeyUp);
    };
  }, [gameStarted, gameOver, gameComplete, isPaused, gameMode, player1Eliminated, player2Eliminated]);

  const getPacmanRotation = () => { switch (direction) { case 'right': return 0; case 'down': return 90; case 'left': return 180; case 'up': return 270; } };

  const getPacmanRotation2 = () => { switch (direction2) { case 'right': return 0; case 'down': return 90; case 'left': return 180; case 'up': return 270; } };

  const renderPacman = () => (
    <svg viewBox="0 0 100 100" className="w-full h-full transition-transform duration-100 ease-out" style={{ transform: `rotate(${getPacmanRotation()}deg)` }}>
      <circle cx="50" cy="50" r="45" fill="hsl(var(--primary))" className="transition-all duration-100 ease-out" />
      {mouthOpen && <path d="M 50 50 L 95 25 L 95 75 Z" fill="hsl(var(--background))" className="transition-all duration-100 ease-out" />}
      <circle cx="50" cy="25" r="6" fill="hsl(var(--background))" className="transition-all duration-100 ease-out" />
    </svg>
  );

  const renderPacman2 = () => (
    <svg viewBox="0 0 100 100" className="w-full h-full transition-transform duration-100 ease-out" style={{ transform: `rotate(${getPacmanRotation2()}deg)` }}>
      <circle cx="50" cy="50" r="45" fill="hsl(120 70% 50%)" className="transition-all duration-100 ease-out" />
      {mouthOpen2 && <path d="M 50 50 L 95 25 L 95 75 Z" fill="hsl(var(--background))" className="transition-all duration-100 ease-out" />}
      <circle cx="50" cy="25" r="6" fill="hsl(var(--background))" className="transition-all duration-100 ease-out" />
    </svg>
  );

  const renderGhost = (index: number, eaten: boolean) => {
    const colors = ['hsl(0 70% 50%)', 'hsl(300 70% 50%)', 'hsl(180 70% 50%)'];
    const scaredColor = 'hsl(220 70% 50%)';
    if (eaten) return null;
    return (
      <svg viewBox="0 0 100 100" className="w-full h-full">
        <path d={`M 10 95 L 10 45 Q 10 5 50 5 Q 90 5 90 45 L 90 95 L 75 80 L 60 95 L 50 80 L 40 95 L 25 80 L 10 95 Z`} fill={isPowered ? scaredColor : colors[index % colors.length]} className={isPowered ? 'animate-pulse' : ''} />
        <ellipse cx="35" cy="45" rx="12" ry="15" fill="white" /><ellipse cx="65" cy="45" rx="12" ry="15" fill="white" />
        <circle cx="38" cy="48" r="6" fill="hsl(var(--background))" /><circle cx="68" cy="48" r="6" fill="hsl(var(--background))" />
      </svg>
    );
  };

  const renderGrid = () => {
    const cells = [];
    const spriteSize = Math.max(cellSize * 0.7, 12);
    for (let y = 0; y < GRID_HEIGHT; y++) {
      for (let x = 0; x < GRID_WIDTH; x++) {
        const isWall = MAZE_TEMPLATE[y][x] === 1;
        const isTunnel = MAZE_TEMPLATE[y][x] === 2;
        const isPacmanHere = pacman.x === x && pacman.y === y;
        const isPacman2Here = gameMode === '2p' && pacman2.x === x && pacman2.y === y;
        const ghostIndex = ghosts.findIndex(g => g.pos.x === x && g.pos.y === y && !g.eaten);
        const isDot = dots.has(`${x},${y}`);
        const isPowerPellet = powerPellets.has(`${x},${y}`);
        cells.push(
          <div key={`${x}-${y}`} className={`flex items-center justify-center transition-all duration-200 ease-out ${isWall ? 'bg-primary/20 border border-primary/40' : isTunnel ? 'bg-background/30' : 'bg-background/50 border border-primary/5'}`} style={{ width: cellSize, height: cellSize }}>
            {isPacmanHere && <div className="drop-shadow-lg" style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out', filter: 'drop-shadow(0 0 4px hsl(var(--primary)))' }}>{renderPacman()}</div>}
            {isPacman2Here && <div className="drop-shadow-lg" style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out', filter: 'drop-shadow(0 0 4px hsl(120 70% 50%))' }}>{renderPacman2()}</div>}
            {ghostIndex !== -1 && !isPacmanHere && !isPacman2Here && <div style={{ width: spriteSize, height: spriteSize, transition: 'all 0.2s ease-out' }}>{renderGhost(ghostIndex, ghosts[ghostIndex].eaten)}</div>}
            {isDot && !isPacmanHere && !isPacman2Here && ghostIndex === -1 && <div className="w-1.5 h-1.5 bg-primary/80 rounded-full transition-all duration-200 ease-out animate-pulse" style={{ animationDuration: '2s' }} />}
            {isPowerPellet && !isPacmanHere && !isPacman2Here && ghostIndex === -1 && <div className="w-3 h-3 bg-primary rounded-full animate-pulse box-glow transition-all duration-200 ease-out" />}
          </div>
        );
      }
    }
    return cells;
  };

  if (showGlitchCrash) return <GlitchCrash onComplete={() => window.location.reload()} />;

  return (
    <motion.div ref={gameRef} tabIndex={0} initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.5 }}
      className={`flex flex-col outline-none ${isFullscreen ? 'fixed inset-0 z-50 bg-background p-4' : 'h-full'}`}>
      <div className="flex items-center justify-between mb-2">
        <div className="flex items-center gap-4">
          <Link to="/games" className="font-pixel text-sm text-foreground/50 hover:text-primary transition-colors">{'<'} Back</Link>
          <h1 className="font-minecraft text-2xl md:text-3xl text-primary text-glow-strong">Pac-Man</h1>
        </div>
        <button onClick={toggleFullscreen} className="p-2 border border-primary/50 hover:bg-primary/20 transition-colors" title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}>
          {isFullscreen ? <Minimize2 size={16} className="text-primary" /> : <Maximize2 size={16} className="text-primary" />}
        </button>
      </div>

      <div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4'} flex-1 ${isFullscreen ? 'justify-center items-center' : ''}`}>
        <div className="border-2 border-primary box-glow p-1 bg-background/80 relative overflow-hidden">
          <div className="absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-primary/5 animate-pulse" style={{ animationDuration: '4s' }}></div>
          <div className="grid relative z-10" style={{ gridTemplateColumns: `repeat(${GRID_WIDTH}, ${cellSize}px)` }}>{renderGrid()}</div>
        </div>

        {!isMobile && (
          <div className="flex flex-col gap-3 min-w-[160px]">
            {/* Score Panel */}
            {gameMode === '2p' ? (
              <div className="border-2 border-primary/50 p-4 bg-background/60">
                <p className="font-pixel text-[10px] text-foreground/50 uppercase tracking-wider mb-2">Scores</p>
                <div className="grid grid-cols-2 gap-3">
                  <div className="text-center">
                    <p className="font-pixel text-[8px] text-primary">P1</p>
                    <p className="font-minecraft text-lg text-primary text-glow">{score.toLocaleString()}</p>
                  </div>
                  <div className="text-center">
                    <p className="font-pixel text-[8px]" style={{ color: 'hsl(120 70% 50%)' }}>P2</p>
                    <p className="font-minecraft text-lg" style={{ color: 'hsl(120 70% 50%)', textShadow: '0 0 10px hsl(120 70% 50%)' }}>{score2.toLocaleString()}</p>
                  </div>
                </div>
              </div>
            ) : (
              <div className="border-2 border-primary/50 p-4 bg-background/60">
                <p className="font-pixel text-[10px] text-foreground/50 uppercase tracking-wider">Score</p>
                <p className="font-minecraft text-2xl text-primary text-glow-strong">{score.toLocaleString()}</p>
              </div>
            )}
            
            {/* High Score */}
            <div className="border border-primary/30 p-3 bg-background/40">
              <p className="font-pixel text-[10px] text-foreground/40 uppercase tracking-wider">High Score</p>
              <p className="font-minecraft text-lg text-primary/80">{highScore.toLocaleString()}</p>
              <p className="font-pixel text-[8px] text-foreground/30 mt-1">max: 4,294,967,296</p>
            </div>
            
            {/* Level & Lives */}
            <div className="grid grid-cols-2 gap-2">
              <div className="border border-primary/30 p-3 bg-background/40 text-center">
                <p className="font-pixel text-[10px] text-foreground/40 uppercase tracking-wider">Level</p>
                <p className="font-minecraft text-xl text-primary">{level}</p>
              </div>
              {gameMode === '2p' ? (
                <div className="border border-primary/30 p-3 bg-background/40">
                  <p className="font-pixel text-[10px] text-foreground/40 uppercase tracking-wider text-center">Lives</p>
                  <div className="flex justify-center gap-2 mt-1">
                    <span className="font-minecraft text-sm text-primary">{lives}</span>
                    <span className="text-foreground/30">/</span>
                    <span className="font-minecraft text-sm" style={{ color: 'hsl(120 70% 50%)' }}>{lives2}</span>
                  </div>
                </div>
              ) : (
                <div className="border border-primary/30 p-3 bg-background/40 text-center">
                  <p className="font-pixel text-[10px] text-foreground/40 uppercase tracking-wider">Lives</p>
                  <p className="font-minecraft text-lg text-primary text-glow">{'♥'.repeat(lives)}</p>
                </div>
              )}
            </div>
            
            {/* Controls */}
            <div className="border border-primary/20 p-3 bg-background/30">
              <p className="font-pixel text-[10px] text-foreground/40 uppercase tracking-wider mb-2">Controls</p>
              {gameMode === '2p' ? (
                <div className="grid grid-cols-2 gap-2 text-center">
                  <div>
                    <p className="font-pixel text-[8px] text-primary">P1</p>
                    <p className="font-pixel text-[9px] text-foreground/60">WASD</p>
                  </div>
                  <div>
                    <p className="font-pixel text-[8px]" style={{ color: 'hsl(120 70% 50%)' }}>P2</p>
                    <p className="font-pixel text-[9px] text-foreground/60">IJKL</p>
                  </div>
                </div>
              ) : (
                <div className="space-y-1">
                  <p className="font-pixel text-[10px] text-foreground/60">WASD / ←→↑↓</p>
                  <p className="font-pixel text-[10px] text-foreground/60">P: Pause</p>
                </div>
              )}
              {gameMode === '2p' && <p className="font-pixel text-[9px] text-foreground/40 text-center mt-2">P: Pause</p>}
            </div>
            
            {/* Action Buttons */}
            {showModeSelection ? (
              <div className="flex flex-col gap-2">
                <p className="font-pixel text-[10px] text-foreground/50 text-center uppercase tracking-wider">Select Mode</p>
                <button onClick={() => { setGameMode('1p'); setShowModeSelection(false); }} className="font-minecraft text-sm py-3 px-4 border-2 border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">1 PLAYER</button>
                <button onClick={() => { setGameMode('2p'); setShowModeSelection(false); }} className="font-minecraft text-sm py-3 px-4 border-2 border-primary/60 bg-background/50 text-primary hover:bg-primary/20 transition-all">2 PLAYERS</button>
              </div>
            ) : !gameStarted || gameOver || gameComplete ? (
              <button onClick={startGame} className="font-minecraft text-sm py-3 px-4 border-2 border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">
                {gameComplete ? 'PERFECT!' : gameOver ? 'RETRY' : 'START GAME'}
              </button>
            ) : (
              <button onClick={() => setIsPaused(p => !p)} className="font-minecraft text-sm py-3 px-4 border-2 border-primary/60 bg-background/50 text-primary hover:bg-primary/20 transition-all">
                {isPaused ? 'RESUME' : 'PAUSE'}
              </button>
            )}
          </div>
        )}

        {isMobile && (
          <>
            <MobileControlsSpacer />
            <MobileControlsDock>
              <div className="flex flex-col items-center gap-2">
                 <div className="flex gap-4 text-center">
                   {gameMode === '2p' ? (
                     <>
                       <div><p className="font-pixel text-[8px] text-foreground/60">P1</p><p className="font-minecraft text-sm text-primary">{score.toLocaleString()}</p></div>
                       <div><p className="font-pixel text-[8px] text-foreground/60">P2</p><p className="font-minecraft text-sm text-primary">{score2.toLocaleString()}</p></div>
                       <div><p className="font-pixel text-[8px] text-foreground/60">LVL</p><p className="font-minecraft text-sm text-primary">{level}</p></div>
                     </>
                   ) : (
                     <>
                       <div><p className="font-pixel text-[8px] text-foreground/60">SCORE</p><p className="font-minecraft text-sm text-primary">{score.toLocaleString()}</p></div>
                       <div><p className="font-pixel text-[8px] text-foreground/60">HIGH</p><p className="font-minecraft text-sm text-primary">{highScore.toLocaleString()}</p></div>
                       <div><p className="font-pixel text-[8px] text-foreground/60">LVL</p><p className="font-minecraft text-sm text-primary">{level}</p></div>
                     </>
                   )}
                   {gameMode === '2p' && (
                     <>
                       <div><p className="font-pixel text-[8px] text-foreground/60">P1</p><p className="font-minecraft text-sm text-primary">{lives}</p></div>
                       <div><p className="font-pixel text-[8px] text-foreground/60">P2</p><p className="font-minecraft text-sm text-primary">{lives2}</p></div>
                     </>
                   )}
                   {gameMode === '1p' && (
                     <div><p className="font-pixel text-[8px] text-foreground/60">LIVES</p><p className="font-minecraft text-sm text-primary">{lives}</p></div>
                   )}
                 </div>

                 {showModeSelection ? (
                   <div className="flex flex-col gap-2 mt-2">
                     <p className="font-pixel text-[10px] text-foreground/60 text-center">MOBILE: 1 PLAYER ONLY</p>
                     <button onClick={() => { setGameMode('1p'); setShowModeSelection(false); }} className="font-minecraft text-sm py-3 px-8 border border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">START GAME</button>
                   </div>
                 ) : gameStarted && !gameOver && !gameComplete ? (
                   useButtonControls ? (
                     <div className="flex flex-col items-center gap-2 mt-2">
                       <button onClick={() => setNextDirection('up')} className="p-3 px-6 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg select-none">↑</button>
                       <div className="flex gap-3">
                         <button onClick={() => setNextDirection('left')} className="p-3 px-6 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg select-none">←</button>
                         <button onClick={() => setIsPaused(p => !p)} className="p-3 px-4 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-[10px] select-none">{isPaused ? '▶' : '❚❚'}</button>
                         <button onClick={() => setNextDirection('right')} className="p-3 px-6 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg select-none">→</button>
                       </div>
                       <button onClick={() => setNextDirection('down')} className="p-3 px-6 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg select-none">↓</button>
                     </div>
                   ) : (
                     <div 
                       className="w-full h-24 border border-primary/30 rounded-lg bg-primary/5 flex items-center justify-center touch-none mt-2"
                       {...getSwipeHandlers()}
                     >
                       <p className="font-pixel text-xs text-primary/60 text-center pointer-events-none">
                         SWIPE TO MOVE<br />
                         <span className="text-[10px] text-foreground/40">TAP TO PAUSE</span>
                       </p>
                     </div>
                   )
                 ) : (
                   <button onClick={startGame} className="font-minecraft text-sm py-3 px-8 border border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">
                     {gameComplete ? 'PERFECT!' : gameOver ? 'RETRY' : 'START'}
                   </button>
                 )}
              </div>
            </MobileControlsDock>
          </>
        )}
      </div>

      {!isMobile && showEliminationPrompt && gameStarted && (
        <div className="fixed inset-0 bg-background/80 flex items-center justify-center z-50">
          <div className="border-2 border-primary box-glow-strong p-6 bg-background text-center">
            <h2 className="font-minecraft text-2xl text-primary text-glow-strong mb-3">{player1Eliminated ? 'PLAYER 2 WON!' : 'PLAYER 1 WON!'}</h2>
            <p className="font-pixel text-sm text-foreground/80 mb-3">
              {player1Eliminated ? 'Player 1' : 'Player 2'} has run out of lives.<br/>
              Continue with the remaining player?
            </p>
            <div className="flex gap-4 justify-center">
              <button onClick={continueIn1PMode} className="font-minecraft text-sm py-2 px-4 border border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">
                CONTINUE (1P)
              </button>
              <button onClick={startGame} className="font-minecraft text-sm py-2 px-4 border border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">
                RESTART
              </button>
            </div>
          </div>
        </div>
      )}

      {!isMobile && (gameOver || isPaused || gameComplete) && gameStarted && !showEliminationPrompt && (
        <div className="fixed inset-0 bg-background/80 flex items-center justify-center z-50">
          <div className="border-2 border-primary box-glow-strong p-6 bg-background text-center">
            <h2 className="font-minecraft text-2xl text-primary text-glow-strong mb-3">{gameComplete ? 'GAME COMPLETE!' : gameOver ? 'GAME OVER' : 'PAUSED'}</h2>
            {(gameOver || gameComplete) && (
              <>
                {gameMode === '2p' ? (
                  <>
                    <p className="font-pixel text-sm text-foreground/80 mb-1">Final Scores</p>
                    <div className="flex gap-4 justify-center mb-1">
                      <div className="text-center"><p className="font-pixel text-xs text-foreground/80">P1</p><p className="font-minecraft text-lg text-primary">{score.toLocaleString()}</p></div>
                      <div className="text-center"><p className="font-pixel text-xs text-foreground/80">P2</p><p className="font-minecraft text-lg text-primary">{score2.toLocaleString()}</p></div>
                    </div>
                  </>
                ) : (
                  <p className="font-pixel text-sm text-foreground/80 mb-1">Final Score: {score.toLocaleString()}</p>
                )}
                <p className="font-pixel text-xs text-foreground/60 mb-3">Level: {level}</p>
              </>
            )}
            <button onClick={(gameOver || gameComplete) ? startGame : () => setIsPaused(false)} className="font-minecraft text-sm py-2 px-6 border border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">{(gameOver || gameComplete) ? 'PLAY AGAIN' : 'RESUME'}</button>
          </div>
        </div>
      )}
    </motion.div>
  );
};

export default Pacman;
