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 GameTouchButton from '@/components/GameTouchButton';
import { MobileControlsDock, MobileControlsSpacer } from '@/components/MobileControlsDock';

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;
}

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 canvasRef = useRef<HTMLCanvasElement>(null);
  const gameRef = useRef<HTMLDivElement>(null);
  const paddleXRef = useRef(160);
  const ballRef = useRef({ x: 200, y: 450, dx: 4, dy: -4 });
  const bricksRef = useRef<Brick[]>([]);
  const keysRef = useRef<Set<string>>(new Set());
  const animationRef = useRef<number>();

  const { enterFullscreen, exitFullscreen } = useBrowserFullscreen();

  const getCanvasSize = useCallback(() => {
    if (typeof window === 'undefined') return { width: 480, height: 580 };
    const isMobile = window.innerWidth < 768;
    if (isMobile) {
      const maxWidth = window.innerWidth - 32;
      // Reserve space for header + fixed controls dock on mobile
      const maxHeight = window.innerHeight - 380;
      const aspectRatio = 480 / 580;
      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 isFullscreen ? { width: 600, height: 720 } : { width: 480, height: 580 };
  }, [isFullscreen]);

  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]);

  const paddleWidth = isMobile ? 70 : (isFullscreen ? 100 : 90);
  const ballSize = isMobile ? 10 : (isFullscreen ? 14 : 12);

  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('breakout', score);
      if (score >= MAX_SCORE) unlockMaxScore();
    }
  }, [score, checkGameScoreAchievements, unlockMaxScore]);

  const initBricks = useCallback(() => {
    const bricks: Brick[] = [];
    const brickWidth = (canvasSize.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%)'];
    for (let row = 0; row < BRICK_ROWS; row++) {
      for (let col = 0; col < BRICK_COLS; col++) {
        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] });
      }
    }
    return bricks;
  }, [canvasSize.width]);

  const resetBall = useCallback(() => {
    const speed = 4 + level * 0.5;
    ballRef.current = { x: canvasSize.width / 2, y: canvasSize.height - 60, dx: (Math.random() > 0.5 ? 1 : -1) * speed, dy: -speed };
    paddleXRef.current = canvasSize.width / 2 - paddleWidth / 2;
  }, [canvasSize.width, canvasSize.height, paddleWidth, level]);

  const startGame = () => {
    setScore(0); setLevel(1); setLives(3); setGameOver(false); setIsPaused(false); setGameStarted(true);
    bricksRef.current = initBricks(); resetBall(); playSound('success'); gameRef.current?.focus();
  };

  const nextLevel = useCallback(() => {
    setLevel(prev => prev + 1); bricksRef.current = initBricks(); resetBall(); playSound('success');
  }, [initBricks, resetBall, playSound]);

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      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]);

  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]);

  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]);

  useEffect(() => {
    if (!gameStarted || gameOver || isPaused) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const gameLoop = () => {
      const paddleSpeed = isMobile ? 6 : (isFullscreen ? 10 : 8);
      if (keysRef.current.has('ArrowLeft') || keysRef.current.has('a')) paddleXRef.current = Math.max(0, paddleXRef.current - paddleSpeed);
      if (keysRef.current.has('ArrowRight') || keysRef.current.has('d')) paddleXRef.current = Math.min(canvasSize.width - paddleWidth, paddleXRef.current + paddleSpeed);

      const ball = ballRef.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 >= paddleXRef.current && ball.x <= paddleXRef.current + paddleWidth) {
        const hitPos = (ball.x - paddleXRef.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) {
        setLives(prev => {
          const newLives = prev - 1;
          if (newLives <= 0) { setGameOver(true); playSound('error'); }
          else { resetBall(); playSound('error'); }
          return newLives;
        });
      }

      let allDestroyed = true;
      for (const brick of bricksRef.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;
          setScore(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('success'); break;
        }
      }

      if (allDestroyed && bricksRef.current.length > 0) nextLevel();

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

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

      for (const brick of bricksRef.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;
      }

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

      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;

      animationRef.current = requestAnimationFrame(gameLoop);
    };

    animationRef.current = requestAnimationFrame(gameLoop);
    return () => { if (animationRef.current) cancelAnimationFrame(animationRef.current); };
  }, [gameStarted, gameOver, isPaused, canvasSize, paddleWidth, ballSize, highScore, isFullscreen, isMobile, playSound, resetBall, nextLevel]);

  useEffect(() => {
    if (gameStarted && !gameOver) { bricksRef.current = initBricks(); resetBall(); }
  }, [canvasSize, gameStarted, gameOver, initBricks, resetBall]);

  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">Breakout</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 bg-background/80">
          <canvas ref={canvasRef} width={canvasSize.width} height={canvasSize.height} onTouchMove={handleTouchMove} className="block" />
        </div>

        {!isMobile && (
          <div className="flex flex-col gap-2 min-w-[140px]">
            <div className="border border-primary/50 p-3 bg-background/50"><p className="font-pixel text-[10px] text-foreground/60">SCORE</p><p className="font-minecraft text-xl text-primary text-glow">{score.toLocaleString()}</p></div>
            <div className="border border-primary/50 p-3 bg-background/50"><p className="font-pixel text-[10px] text-foreground/60">HIGH SCORE</p><p className="font-minecraft text-lg text-primary text-glow">{highScore.toLocaleString()}</p><p className="font-pixel text-[8px] text-foreground/30">max: 4,294,967,296</p></div>
            <div className="border border-primary/50 p-3 bg-background/50"><p className="font-pixel text-[10px] text-foreground/60">LEVEL</p><p className="font-minecraft text-lg text-primary text-glow">{level}</p></div>
            <div className="border border-primary/50 p-3 bg-background/50"><p className="font-pixel text-[10px] text-foreground/60">LIVES</p><p className="font-minecraft text-lg text-primary text-glow">{'♥'.repeat(lives)}</p></div>
            <div className="border border-primary/50 p-3 bg-background/50"><p className="font-pixel text-[10px] text-foreground/60 mb-1">CONTROLS</p><p className="font-pixel text-[10px] text-foreground/80">← → / A D</p><p className="font-pixel text-[10px] text-foreground/80">P: Pause</p></div>
            {!gameStarted || gameOver ? (
              <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">{gameOver ? 'RETRY' : 'START'}</button>
            ) : (
              <button onClick={() => setIsPaused(p => !p)} className="font-minecraft text-sm py-2 px-4 border border-primary bg-primary/20 text-primary hover:bg-primary/40 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>
                ) : (
                  <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">{gameOver ? 'RETRY' : 'START'}</button>
                )}
              </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 && (<><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 ? 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 ? 'PLAY AGAIN' : 'RESUME'}</button>
          </div>
        </div>
      )}
    </motion.div>
  );
};

export default Breakout;
