import { useState, useEffect, useCallback, useRef } from 'react';
import { createPortal } from 'react-dom';
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 GameTouchButton from '@/components/GameTouchButton';
import { MobileControlsDock, MobileControlsSpacer } from '@/components/MobileControlsDock';
import MatrixCursor from '@/components/MatrixCursor';

const PADDLE_HEIGHT = 14;
const BRICK_ROWS = 6;
const BRICK_COLS = 10;
const BRICK_HEIGHT = 20;
const BRICK_GAP = 4;
const MAX_SCORE = 4294967296;
const HIGHSCORE_KEY = 'breakout-highscore';

interface Brick {
  x: number;
  y: number;
  width: number;
  height: number;
  alive: boolean;
  color: string;
  hasPowerUp?: PowerUpType;
}

type PowerUpType = 'wide' | 'multi' | 'slow' | 'life';

interface PowerUp {
  x: number;
  y: number;
  type: PowerUpType;
  active: boolean;
}

const POWER_UP_COLORS: Record<PowerUpType, string> = {
  wide: 'hsl(200 80% 60%)',
  multi: 'hsl(280 80% 60%)',
  slow: 'hsl(45 80% 60%)',
  life: 'hsl(0 80% 60%)',
};

const POWER_UP_LABELS: Record<PowerUpType, string> = {
  wide: 'W',
  multi: 'M',
  slow: 'S',
  life: '+',
};

const Breakout = () => {
  const { playSound } = useSettings();
  const { checkGameScoreAchievements, unlockMaxScore } = useAchievements();
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [score, setScore] = useState(0);
  const [highScore, setHighScore] = useState(0);
  const [level, setLevel] = useState(1);
  const [lives, setLives] = useState(3);
  const [gameOver, setGameOver] = useState(false);
  const [gameStarted, setGameStarted] = useState(false);
  const [isPaused, setIsPaused] = useState(false);
  const [showGlitchCrash, setShowGlitchCrash] = useState(false);
  const [isTwoPlayer, setIsTwoPlayer] = useState(false);

  // Power-up state
  const [activePowerUps, setActivePowerUps] = useState<{ type: PowerUpType; endTime: number }[]>([]);
  const powerUpsRef = useRef<PowerUp[]>([]);
  const extraBallsRef = useRef<{ x: number; y: number; dx: number; dy: number }[]>([]);
  const basePaddleWidth = useRef(90);

  // P2 state
  const [score2, setScore2] = useState(0);
  const [lives2, setLives2] = useState(3);
  const [level2, setLevel2] = useState(1);

  const canvasRef = useRef<HTMLCanvasElement>(null);
  const canvas2Ref = useRef<HTMLCanvasElement>(null);
  const gameRef = useRef<HTMLDivElement>(null);
  const paddleXRef = useRef(160);
  const paddle2XRef = useRef(160);
  const ballRef = useRef({ x: 200, y: 450, dx: 4, dy: -4 });
  const ball2Ref = useRef({ x: 200, y: 450, dx: 4, dy: -4 });
  const bricksRef = useRef<Brick[]>([]);
  const bricks2Ref = useRef<Brick[]>([]);
  const keysRef = useRef<Set<string>>(new Set());
  const animationRef = useRef<number>();
  const animation2Ref = useRef<number>();
  const p1DeadRef = useRef(false);
  const p2DeadRef = useRef(false);

  const { enterFullscreen, exitFullscreen } = useBrowserFullscreen();

  const getCanvasSize = useCallback(() => {
    if (typeof window === 'undefined') return { width: 560, height: 680 };
    const isMobile = window.innerWidth < 768;
    if (isMobile) {
      const maxWidth = window.innerWidth - 32;
      const maxHeight = window.innerHeight - 380;
      const aspectRatio = 560 / 680;
      let width = maxWidth;
      let height = width / aspectRatio;
      if (height > maxHeight) { height = maxHeight; width = height * aspectRatio; }
      return { width: Math.floor(width), height: Math.floor(height) };
    }
    if (isFullscreen) {
      const aspectRatio = 560 / 680;
      if (isTwoPlayer) {
        // Two canvases side by side
        const maxWidth = (window.innerWidth - 100) / 2;
        const maxHeight = window.innerHeight - 120;
        let width = maxWidth;
        let height = width / aspectRatio;
        if (height > maxHeight) { height = maxHeight; width = height * aspectRatio; }
        return { width: Math.floor(width), height: Math.floor(height) };
      }
      // Single player - fill screen
      const maxWidth = window.innerWidth - 280;
      const maxHeight = window.innerHeight - 100;
      let width = maxWidth;
      let height = width / aspectRatio;
      if (height > maxHeight) { height = maxHeight; width = height * aspectRatio; }
      return { width: Math.floor(width), height: Math.floor(height) };
    }
    return isTwoPlayer ? { width: 400, height: 500 } : { width: 560, height: 680 };
  }, [isFullscreen, isTwoPlayer]);

  const [canvasSize, setCanvasSize] = useState(getCanvasSize);
  const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;

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

  useEffect(() => { setCanvasSize(getCanvasSize()); }, [isFullscreen, getCanvasSize, isTwoPlayer]);

  // Calculate paddle width based on active power-ups
  const hasWidePaddle = activePowerUps.some(p => p.type === 'wide' && p.endTime > Date.now());
  const hasSlowBall = activePowerUps.some(p => p.type === 'slow' && p.endTime > Date.now());
  basePaddleWidth.current = isMobile ? 70 : (isTwoPlayer ? 70 : (isFullscreen ? 100 : 90));
  const paddleWidth = hasWidePaddle ? basePaddleWidth.current * 1.5 : basePaddleWidth.current;
  const ballSize = isMobile ? 10 : (isTwoPlayer ? 10 : (isFullscreen ? 14 : 12));

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

  // Prevent page scroll while in fullscreen mode (portal overlays the viewport)
  useEffect(() => {
    if (typeof document === 'undefined') return;
    if (!isFullscreen) return;
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prevOverflow; };
  }, [isFullscreen]);

  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));
  }, []);

  useEffect(() => {
    if (score > 0) {
      checkGameScoreAchievements('breakout', score);
      if (score >= MAX_SCORE) unlockMaxScore();
    }
  }, [score, checkGameScoreAchievements, unlockMaxScore]);

  const initBricks = useCallback((width: number) => {
    const bricks: Brick[] = [];
    const brickWidth = (width - (BRICK_COLS + 1) * BRICK_GAP) / BRICK_COLS;
    const colors = ['hsl(0 70% 50%)', 'hsl(30 70% 50%)', 'hsl(60 70% 50%)', 'hsl(120 70% 50%)', 'hsl(200 70% 50%)', 'hsl(280 70% 50%)'];
    const powerUpTypes: PowerUpType[] = ['wide', 'multi', 'slow', 'life'];
    
    for (let row = 0; row < BRICK_ROWS; row++) {
      for (let col = 0; col < BRICK_COLS; col++) {
        // ~15% chance of having a power-up
        const hasPowerUp = Math.random() < 0.15;
        const powerUpType = hasPowerUp ? powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)] : undefined;
        
        bricks.push({ 
          x: BRICK_GAP + col * (brickWidth + BRICK_GAP), 
          y: 60 + row * (BRICK_HEIGHT + BRICK_GAP), 
          width: brickWidth, 
          height: BRICK_HEIGHT, 
          alive: true, 
          color: colors[row % colors.length],
          hasPowerUp: powerUpType
        });
      }
    }
    return bricks;
  }, []);

  const resetBall = useCallback((ballRefToReset: React.MutableRefObject<{x: number, y: number, dx: number, dy: number}>, paddleRefToReset: React.MutableRefObject<number>, lvl: number) => {
    // Slower base speed for classic Breakout feel (was 2.5)
    const speed = 1.8 + lvl * 0.2;
    ballRefToReset.current = { x: canvasSize.width / 2, y: canvasSize.height - 60, dx: (Math.random() > 0.5 ? 1 : -1) * speed, dy: -speed };
    paddleRefToReset.current = canvasSize.width / 2 - paddleWidth / 2;
  }, [canvasSize.width, canvasSize.height, paddleWidth]);

  const startGame = (twoPlayer: boolean) => {
    setIsTwoPlayer(twoPlayer);
    setScore(0); setLevel(1); setLives(3); setGameOver(false); setIsPaused(false); setGameStarted(true);
    setActivePowerUps([]);
    powerUpsRef.current = [];
    extraBallsRef.current = [];
    p1DeadRef.current = false;
    p2DeadRef.current = false;
    
    if (twoPlayer) {
      setScore2(0); setLevel2(1); setLives2(3);
    }
    
    setTimeout(() => {
      const size = getCanvasSize();
      bricksRef.current = initBricks(size.width);
      resetBall(ballRef, paddleXRef, 1);
      
      if (twoPlayer) {
        bricks2Ref.current = initBricks(size.width);
        resetBall(ball2Ref, paddle2XRef, 1);
      }
    }, 50);
    
    playSound('success');
    gameRef.current?.focus();
  };

  const nextLevel = useCallback((player: 1 | 2) => {
    if (player === 1) {
      setLevel(prev => {
        const newLevel = prev + 1;
        bricksRef.current = initBricks(canvasSize.width);
        resetBall(ballRef, paddleXRef, newLevel);
        return newLevel;
      });
    } else {
      setLevel2(prev => {
        const newLevel = prev + 1;
        bricks2Ref.current = initBricks(canvasSize.width);
        resetBall(ball2Ref, paddle2XRef, newLevel);
        return newLevel;
      });
    }
    playSound('success');
  }, [initBricks, resetBall, playSound, canvasSize.width]);

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (isTwoPlayer) {
        // P1: A/D, P2: Arrow keys
        if (['a', 'd', 'ArrowLeft', 'ArrowRight'].includes(e.key)) { e.preventDefault(); keysRef.current.add(e.key); }
      } else {
        if (['ArrowLeft', 'ArrowRight', 'a', 'd'].includes(e.key)) { e.preventDefault(); keysRef.current.add(e.key); }
      }
      if (e.key === 'p' && gameStarted && !gameOver) { setIsPaused(prev => !prev); playSound('click'); }
    };
    const handleKeyUp = (e: KeyboardEvent) => { keysRef.current.delete(e.key); };
    window.addEventListener('keydown', handleKeyDown);
    window.addEventListener('keyup', handleKeyUp);
    return () => { window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keyup', handleKeyUp); };
  }, [gameStarted, gameOver, playSound, isTwoPlayer]);

  const handleTouchMove = useCallback((e: React.TouchEvent) => {
    if (!gameStarted || gameOver || isPaused) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const rect = canvas.getBoundingClientRect();
    const touch = e.touches[0];
    const x = touch.clientX - rect.left;
    paddleXRef.current = Math.max(0, Math.min(canvasSize.width - paddleWidth, x - paddleWidth / 2));
  }, [gameStarted, gameOver, isPaused, canvasSize.width, paddleWidth]);

  // Mouse move handler for desktop
  const handleMouseMove = useCallback((e: React.MouseEvent) => {
    if (!gameStarted || gameOver || isPaused || isMobile || isTwoPlayer) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left;
    paddleXRef.current = Math.max(0, Math.min(canvasSize.width - paddleWidth, x - paddleWidth / 2));
  }, [gameStarted, gameOver, isPaused, canvasSize.width, paddleWidth, isMobile, isTwoPlayer]);

  const moveLeft = useCallback(() => { paddleXRef.current = Math.max(0, paddleXRef.current - 20); }, []);
  const moveRight = useCallback(() => { paddleXRef.current = Math.min(canvasSize.width - paddleWidth, paddleXRef.current + 20); }, [canvasSize.width, paddleWidth]);

  // Game loop for a player
  const runGameLoop = useCallback((
    canvas: HTMLCanvasElement,
    ballRefParam: React.MutableRefObject<{x: number, y: number, dx: number, dy: number}>,
    paddleRefParam: React.MutableRefObject<number>,
    bricksRefParam: React.MutableRefObject<Brick[]>,
    setScoreParam: React.Dispatch<React.SetStateAction<number>>,
    setLivesParam: React.Dispatch<React.SetStateAction<number>>,
    getLives: () => number,
    playerNum: 1 | 2,
    primaryColor: string,
    leftKey: string,
    rightKey: string,
    deadRef: React.MutableRefObject<boolean>
  ) => {
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const paddleSpeed = isMobile ? 4 : (isFullscreen ? 6 : 5);
    if (keysRef.current.has(leftKey)) paddleRefParam.current = Math.max(0, paddleRefParam.current - paddleSpeed);
    if (keysRef.current.has(rightKey)) paddleRefParam.current = Math.min(canvasSize.width - paddleWidth, paddleRefParam.current + paddleSpeed);

    const ball = ballRefParam.current;
    ball.x += ball.dx; ball.y += ball.dy;

    if (ball.x <= ballSize / 2 || ball.x >= canvasSize.width - ballSize / 2) { ball.dx = -ball.dx; playSound('hover'); }
    if (ball.y <= ballSize / 2) { ball.dy = -ball.dy; playSound('hover'); }

    const paddleY = canvasSize.height - 30;
    if (ball.y + ballSize / 2 >= paddleY && ball.y - ballSize / 2 <= paddleY + PADDLE_HEIGHT && ball.x >= paddleRefParam.current && ball.x <= paddleRefParam.current + paddleWidth) {
      const hitPos = (ball.x - paddleRefParam.current) / paddleWidth;
      const angle = (hitPos - 0.5) * Math.PI * 0.7;
      const speed = Math.sqrt(ball.dx * ball.dx + ball.dy * ball.dy);
      ball.dx = Math.sin(angle) * speed; ball.dy = -Math.abs(Math.cos(angle) * speed);
      ball.y = paddleY - ballSize / 2; playSound('click');
    }

    if (ball.y >= canvasSize.height && !deadRef.current) {
      const currentLives = getLives();
      const newLives = currentLives - 1;
      setLivesParam(newLives);
      if (newLives <= 0) {
        deadRef.current = true;
        playSound('error');
        // Check if game over (both players dead in 2P, or single player dead)
        if (!isTwoPlayer) {
          setGameOver(true);
        } else {
          // Check if both dead
          if ((playerNum === 1 && p2DeadRef.current) || (playerNum === 2 && p1DeadRef.current)) {
            setGameOver(true);
          }
        }
      } else {
        resetBall(ballRefParam, paddleRefParam, playerNum === 1 ? level : level2);
        playSound('error');
      }
    }

    let allDestroyed = true;
    for (const brick of bricksRefParam.current) {
      if (!brick.alive) continue;
      allDestroyed = false;
      if (ball.x + ballSize / 2 >= brick.x && ball.x - ballSize / 2 <= brick.x + brick.width && ball.y + ballSize / 2 >= brick.y && ball.y - ballSize / 2 <= brick.y + brick.height) {
        brick.alive = false; ball.dy = -ball.dy;
        
        // Spawn power-up if brick had one (P1 only for simplicity)
        if (brick.hasPowerUp && playerNum === 1) {
          powerUpsRef.current.push({
            x: brick.x + brick.width / 2,
            y: brick.y + brick.height,
            type: brick.hasPowerUp,
            active: true
          });
        }
        
        setScoreParam(prev => {
          const ns = Math.min(prev + 10, MAX_SCORE);
          if (ns >= MAX_SCORE && playerNum === 1) setShowGlitchCrash(true);
          if (ns > highScore && playerNum === 1) { setHighScore(ns); localStorage.setItem(HIGHSCORE_KEY, ns.toString()); }
          return ns;
        });
        playSound('success'); break;
      }
    }
    
    // Update power-ups (P1 only)
    if (playerNum === 1) {
      const paddleY = canvasSize.height - 30;
      for (const pu of powerUpsRef.current) {
        if (!pu.active) continue;
        pu.y += 2; // Fall speed
        
        // Check paddle collision
        if (pu.y >= paddleY && pu.y <= paddleY + PADDLE_HEIGHT && pu.x >= paddleRefParam.current && pu.x <= paddleRefParam.current + paddleWidth) {
          pu.active = false;
          playSound('success');
          
          if (pu.type === 'life') {
            setLivesParam(prev => Math.min(prev + 1, 5));
          } else if (pu.type === 'multi') {
            // Add extra ball
            const newBall = { x: ball.x, y: ball.y, dx: -ball.dx, dy: ball.dy };
            extraBallsRef.current.push(newBall);
          } else {
            // Wide or Slow - timed power-up (8 seconds)
            setActivePowerUps(prev => [...prev.filter(p => p.type !== pu.type), { type: pu.type, endTime: Date.now() + 8000 }]);
          }
        }
        
        // Remove if off screen
        if (pu.y > canvasSize.height) pu.active = false;
      }
      powerUpsRef.current = powerUpsRef.current.filter(pu => pu.active);
      
      // Update extra balls
      for (const eb of extraBallsRef.current) {
        const speedMod = hasSlowBall ? 0.6 : 1;
        eb.x += eb.dx * speedMod; eb.y += eb.dy * speedMod;
        if (eb.x <= ballSize / 2 || eb.x >= canvasSize.width - ballSize / 2) eb.dx = -eb.dx;
        if (eb.y <= ballSize / 2) eb.dy = -eb.dy;
        if (eb.y + ballSize / 2 >= paddleY && eb.y - ballSize / 2 <= paddleY + PADDLE_HEIGHT && eb.x >= paddleRefParam.current && eb.x <= paddleRefParam.current + paddleWidth) {
          const hitPos = (eb.x - paddleRefParam.current) / paddleWidth;
          const angle = (hitPos - 0.5) * Math.PI * 0.7;
          const speed = Math.sqrt(eb.dx * eb.dx + eb.dy * eb.dy);
          eb.dx = Math.sin(angle) * speed; eb.dy = -Math.abs(Math.cos(angle) * speed);
          eb.y = paddleY - ballSize / 2;
        }
      }
      extraBallsRef.current = extraBallsRef.current.filter(eb => eb.y < canvasSize.height);
    }

    if (allDestroyed && bricksRefParam.current.length > 0 && !deadRef.current) nextLevel(playerNum);

    ctx.fillStyle = '#0a0a0a'; ctx.fillRect(0, 0, canvasSize.width, canvasSize.height);

    for (const brick of bricksRefParam.current) {
      if (!brick.alive) continue;
      ctx.fillStyle = brick.color; ctx.fillRect(brick.x, brick.y, brick.width, brick.height);
      ctx.strokeStyle = primaryColor; ctx.globalAlpha = 0.5; ctx.strokeRect(brick.x, brick.y, brick.width, brick.height); ctx.globalAlpha = 1;
      // Draw power-up indicator
      if (brick.hasPowerUp) {
        ctx.fillStyle = POWER_UP_COLORS[brick.hasPowerUp];
        ctx.font = '10px monospace';
        ctx.textAlign = 'center';
        ctx.fillText(POWER_UP_LABELS[brick.hasPowerUp], brick.x + brick.width / 2, brick.y + brick.height / 2 + 3);
      }
    }

    // Draw falling power-ups
    if (playerNum === 1) {
      for (const pu of powerUpsRef.current) {
        if (!pu.active) continue;
        ctx.fillStyle = POWER_UP_COLORS[pu.type];
        ctx.shadowColor = POWER_UP_COLORS[pu.type]; ctx.shadowBlur = 8;
        ctx.beginPath(); ctx.arc(pu.x, pu.y, 8, 0, Math.PI * 2); ctx.fill();
        ctx.fillStyle = '#000'; ctx.font = 'bold 10px monospace'; ctx.textAlign = 'center';
        ctx.fillText(POWER_UP_LABELS[pu.type], pu.x, pu.y + 4); ctx.shadowBlur = 0;
      }
    }

    ctx.fillStyle = primaryColor; ctx.shadowColor = primaryColor; ctx.shadowBlur = 10;
    ctx.fillRect(paddleRefParam.current, canvasSize.height - 30, paddleWidth, PADDLE_HEIGHT); ctx.shadowBlur = 0;

    if (!deadRef.current) {
      ctx.beginPath(); ctx.arc(ball.x, ball.y, ballSize / 2, 0, Math.PI * 2);
      ctx.fillStyle = primaryColor; ctx.shadowColor = primaryColor; ctx.shadowBlur = 15; ctx.fill(); ctx.shadowBlur = 0;
    }

    ctx.strokeStyle = primaryColor; ctx.globalAlpha = 0.5; ctx.lineWidth = 2;
    ctx.strokeRect(0, 0, canvasSize.width, canvasSize.height); ctx.globalAlpha = 1;

    // Draw player label in 2P mode
    if (isTwoPlayer) {
      ctx.font = '14px monospace';
      ctx.fillStyle = primaryColor;
      ctx.textAlign = 'center';
      ctx.fillText(`P${playerNum}`, canvasSize.width / 2, 20);
      
      if (deadRef.current) {
        ctx.font = '20px monospace';
        ctx.fillStyle = 'hsl(0 70% 50%)';
        ctx.fillText('ELIMINATED', canvasSize.width / 2, canvasSize.height / 2);
      }
    }
  }, [canvasSize, paddleWidth, ballSize, highScore, isFullscreen, isMobile, playSound, resetBall, nextLevel, isTwoPlayer, level, level2]);

  // P1 game loop
  useEffect(() => {
    if (!gameStarted || gameOver || isPaused) return;
    const canvas = canvasRef.current;
    if (!canvas) return;

    const computedStyle = getComputedStyle(document.documentElement);
    const primaryHsl = computedStyle.getPropertyValue('--primary').trim();
    const primaryColor = `hsl(${primaryHsl})`;

    const gameLoop = () => {
      const leftKey = isTwoPlayer ? 'a' : 'ArrowLeft';
      const rightKey = isTwoPlayer ? 'd' : 'ArrowRight';
      const altLeftKey = isTwoPlayer ? '' : 'a';
      const altRightKey = isTwoPlayer ? '' : 'd';
      
      // Check both keys in single player
      const checkLeft = leftKey;
      const checkRight = rightKey;
      
      if (!isTwoPlayer) {
        // In single player, check both arrow and A/D
        if (keysRef.current.has('ArrowLeft') || keysRef.current.has('a')) {
          keysRef.current.add('ArrowLeft');
        }
        if (keysRef.current.has('ArrowRight') || keysRef.current.has('d')) {
          keysRef.current.add('ArrowRight');
        }
      }
      
      runGameLoop(canvas, ballRef, paddleXRef, bricksRef, setScore, setLives, () => lives, 1, primaryColor, checkLeft, checkRight, p1DeadRef);
      animationRef.current = requestAnimationFrame(gameLoop);
    };

    animationRef.current = requestAnimationFrame(gameLoop);
    return () => { if (animationRef.current) cancelAnimationFrame(animationRef.current); };
  }, [gameStarted, gameOver, isPaused, runGameLoop, isTwoPlayer, lives]);

  // P2 game loop
  useEffect(() => {
    if (!gameStarted || gameOver || isPaused || !isTwoPlayer) return;
    const canvas = canvas2Ref.current;
    if (!canvas) return;

    const computedStyle = getComputedStyle(document.documentElement);
    const secondaryHsl = computedStyle.getPropertyValue('--secondary').trim();
    const secondaryColor = `hsl(${secondaryHsl})`;

    const gameLoop = () => {
      runGameLoop(canvas, ball2Ref, paddle2XRef, bricks2Ref, setScore2, setLives2, () => lives2, 2, secondaryColor, 'ArrowLeft', 'ArrowRight', p2DeadRef);
      animation2Ref.current = requestAnimationFrame(gameLoop);
    };

    animation2Ref.current = requestAnimationFrame(gameLoop);
    return () => { if (animation2Ref.current) cancelAnimationFrame(animation2Ref.current); };
  }, [gameStarted, gameOver, isPaused, isTwoPlayer, runGameLoop, lives2]);

  useEffect(() => {
    if (gameStarted && !gameOver) {
      bricksRef.current = initBricks(canvasSize.width);
      resetBall(ballRef, paddleXRef, level);
      if (isTwoPlayer) {
        bricks2Ref.current = initBricks(canvasSize.width);
        resetBall(ball2Ref, paddle2XRef, level2);
      }
    }
  }, [canvasSize, gameStarted, gameOver, initBricks, resetBall, isTwoPlayer, level, level2]);

  const getWinner = () => {
    if (!isTwoPlayer) return null;
    if (score > score2) return 'P1';
    if (score2 > score) return 'P2';
    return 'TIE';
  };

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

  const gameUi = (
    <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-[100] bg-background p-4 w-screen h-screen' : 'h-full'}`}>
      {/* Render cursor inside portal for fullscreen */}
      {isFullscreen && <MatrixCursor />}
      <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">Breakout</h1>
          {isTwoPlayer && <span className="font-pixel text-xs text-secondary">2P MODE</span>}
        </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' : ''}`}>
        {/* Game boards */}
        <div className={`flex ${isTwoPlayer ? 'gap-4' : ''}`}>
          {/* P1 Board */}
          <div className="border-2 border-primary box-glow bg-background/80">
            <canvas ref={canvasRef} width={canvasSize.width} height={canvasSize.height} onTouchMove={handleTouchMove} onMouseMove={handleMouseMove} className="block cursor-none" />
          </div>

          {/* P2 Board */}
          {isTwoPlayer && !isMobile && (
            <div className="border-2 border-secondary bg-background/80" style={{ boxShadow: '0 0 20px hsl(var(--secondary) / 0.3)' }}>
              <canvas ref={canvas2Ref} width={canvasSize.width} height={canvasSize.height} className="block" />
            </div>
          )}
        </div>

        {!isMobile && (
          <div className="flex flex-col gap-3 min-w-[160px]">
            {/* P1 Score Panel */}
            <div className="border-2 border-primary/50 p-4 bg-background/60">
              <p className="font-pixel text-[10px] text-foreground/50 uppercase tracking-wider">{isTwoPlayer ? 'P1 Score' : 'Score'}</p>
              <p className="font-minecraft text-2xl text-primary text-glow-strong">{score.toLocaleString()}</p>
            </div>

            {/* P2 Score Panel */}
            {isTwoPlayer && (
              <div className="border-2 border-secondary/50 p-4 bg-background/60">
                <p className="font-pixel text-[10px] text-foreground/50 uppercase tracking-wider">P2 Score</p>
                <p className="font-minecraft text-2xl text-secondary">{score2.toLocaleString()}</p>
              </div>
            )}
            
            {!isTwoPlayer && (
              <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">{isTwoPlayer ? 'P1 Lvl' : 'Level'}</p>
                <p className="font-minecraft text-xl text-primary">{level}</p>
              </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">{isTwoPlayer ? 'P1 ♥' : 'Lives'}</p>
                <p className="font-minecraft text-lg text-primary text-glow">{'♥'.repeat(Math.max(0, lives))}</p>
              </div>
            </div>

            {isTwoPlayer && (
              <div className="grid grid-cols-2 gap-2">
                <div className="border border-secondary/30 p-3 bg-background/40 text-center">
                  <p className="font-pixel text-[10px] text-foreground/40 uppercase tracking-wider">P2 Lvl</p>
                  <p className="font-minecraft text-xl text-secondary">{level2}</p>
                </div>
                <div className="border border-secondary/30 p-3 bg-background/40 text-center">
                  <p className="font-pixel text-[10px] text-foreground/40 uppercase tracking-wider">P2 ♥</p>
                  <p className="font-minecraft text-lg text-secondary">{'♥'.repeat(Math.max(0, lives2))}</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>
              <div className="space-y-1">
                {isTwoPlayer ? (
                  <>
                    <p className="font-pixel text-[10px] text-primary">P1: A / D</p>
                    <p className="font-pixel text-[10px] text-secondary">P2: ← →</p>
                  </>
                ) : (
                  <p className="font-pixel text-[10px] text-foreground/60">← → / A D</p>
                )}
                <p className="font-pixel text-[10px] text-foreground/60">P: Pause</p>
              </div>
            </div>
            
            {/* Action Buttons */}
            {!gameStarted || gameOver ? (
              <div className="flex flex-col gap-2">
                <button onClick={() => startGame(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">
                  {gameOver ? 'RETRY 1P' : '1 PLAYER'}
                </button>
                <button onClick={() => startGame(true)} className="font-minecraft text-sm py-3 px-4 border-2 border-secondary bg-secondary/20 text-secondary hover:bg-secondary/40 transition-all">
                  {gameOver ? 'RETRY 2P' : '2 PLAYERS'}
                </button>
              </div>
            ) : (
              <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 heightClassName="h-36" />
            <MobileControlsDock>
              <div className="flex flex-col items-center gap-2">
                <div className="flex gap-4 text-center">
                  <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>
                  <div><p className="font-pixel text-[8px] text-foreground/60">♥</p><p className="font-minecraft text-sm text-primary">{lives}</p></div>
                </div>

                {gameStarted && !gameOver ? (
                  <div className="flex gap-3 mt-2">
                    <GameTouchButton onAction={moveLeft} className="p-4 px-8 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg" interval={30}>←</GameTouchButton>
                    <button onClick={() => setIsPaused(p => !p)} className="p-4 px-6 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-[10px] select-none">{isPaused ? '▶' : '❚❚'}</button>
                    <GameTouchButton onAction={moveRight} className="p-4 px-8 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg" interval={30}>→</GameTouchButton>
                  </div>
                ) : (
                  <div className="flex flex-col gap-2 items-center">
                    <button onClick={() => startGame(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">{gameOver ? 'RETRY' : 'START'}</button>
                    <p className="font-pixel text-[8px] text-foreground/40">MOBILE: 1 PLAYER ONLY</p>
                  </div>
                )}
              </div>
            </MobileControlsDock>
          </>
        )}
      </div>

      {!isMobile && (gameOver || isPaused) && 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">{gameOver ? 'GAME OVER' : 'PAUSED'}</h2>
            {gameOver && isTwoPlayer && (
              <p className="font-minecraft text-xl mb-2" style={{ color: getWinner() === 'P1' ? 'hsl(var(--primary))' : getWinner() === 'P2' ? 'hsl(var(--secondary))' : 'hsl(var(--foreground))' }}>
                {getWinner() === 'TIE' ? "IT'S A TIE!" : `${getWinner()} WINS!`}
              </p>
            )}
            {gameOver && (
              <div className="mb-4">
                <p className="font-pixel text-sm text-foreground/60">{isTwoPlayer ? 'P1: ' : 'Score: '}{score.toLocaleString()}</p>
                {isTwoPlayer && <p className="font-pixel text-sm text-foreground/60">P2: {score2.toLocaleString()}</p>}
              </div>
            )}
            <div className="flex gap-3 justify-center">
              <Link to="/games" className="font-minecraft text-sm py-2 px-4 border border-foreground/50 text-foreground/70 hover:bg-foreground/10 transition-all">Back</Link>
              {gameOver ? (
                <>
                  <button onClick={() => startGame(false)} className="font-minecraft text-sm py-2 px-4 border-2 border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">1P</button>
                  <button onClick={() => startGame(true)} className="font-minecraft text-sm py-2 px-4 border-2 border-secondary bg-secondary/20 text-secondary hover:bg-secondary/40 transition-all">2P</button>
                </>
              ) : (
                <button onClick={() => setIsPaused(false)} className="font-minecraft text-sm py-2 px-4 border-2 border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all box-glow">Resume</button>
              )}
            </div>
          </div>
        </div>
      )}
    </motion.div>
  );

  // Portal to body for true fullscreen, escaping MainLayout transforms
  return isFullscreen && typeof document !== 'undefined'
    ? createPortal(gameUi, document.body)
    : gameUi;
};

export default Breakout;
