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 GRID_SIZE = 20;
const TICK_SPEED = 120;
const MAX_SCORE = 4294967296;
const HIGHSCORE_KEY = 'snake-highscore';

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

const Snake = () => {
  const { playSound } = useSettings();
  const { checkGameScoreAchievements, unlockMaxScore } = useAchievements();
  const [snake, setSnake] = useState<Position[]>([{ x: 10, y: 10 }]);
  const [direction, setDirection] = useState<Direction>('right');
  const [food, setFood] = useState<Position>({ x: 15, y: 10 });
  const [score, setScore] = 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 [isFullscreen, setIsFullscreen] = useState(false);
  const gameRef = useRef<HTMLDivElement>(null);
  const directionQueueRef = useRef<Direction[]>([]);
  const currentDirectionRef = useRef<Direction>('right');

  const { enterFullscreen, exitFullscreen } = useBrowserFullscreen();

  // Calculate cell size based on screen
  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_SIZE), Math.floor(maxHeight / GRID_SIZE), 18);
    }
    return isFullscreen ? 28 : 24;
  }, [isFullscreen]);

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

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

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

  // Auto-fullscreen on mobile
  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('snake', score);
      if (score >= MAX_SCORE) unlockMaxScore();
    }
  }, [score, checkGameScoreAchievements, unlockMaxScore]);

  const spawnFood = useCallback((currentSnake: Position[]): Position | null => {
    const occupied = new Set(currentSnake.map(s => `${s.x},${s.y}`));
    const available: Position[] = [];
    for (let x = 0; x < GRID_SIZE; x++) {
      for (let y = 0; y < GRID_SIZE; y++) {
        if (!occupied.has(`${x},${y}`)) available.push({ x, y });
      }
    }
    if (available.length === 0) return null;
    return available[Math.floor(Math.random() * available.length)];
  }, []);

  const resetSnakeKeepScore = useCallback(() => {
    const initialSnake = [{ x: 10, y: 10 }];
    setSnake(initialSnake);
    setDirection('right');
    currentDirectionRef.current = 'right';
    directionQueueRef.current = [];
    setFood(spawnFood(initialSnake)!);
    playSound('success');
  }, [spawnFood, playSound]);

  const startGame = () => {
    const initialSnake = [{ x: 10, y: 10 }];
    setSnake(initialSnake);
    setDirection('right');
    currentDirectionRef.current = 'right';
    directionQueueRef.current = [];
    setFood(spawnFood(initialSnake)!);
    setScore(0);
    setGameOver(false);
    setGameComplete(false);
    setIsPaused(false);
    setGameStarted(true);
    playSound('success');
    gameRef.current?.focus();
  };

  useEffect(() => {
    if (!gameStarted || gameOver || gameComplete || isPaused) return;

    const interval = setInterval(() => {
      const opposite: Record<Direction, Direction> = { up: 'down', down: 'up', left: 'right', right: 'left' };
      let nextDir = currentDirectionRef.current;
      while (directionQueueRef.current.length > 0) {
        const queuedDir = directionQueueRef.current.shift()!;
        if (queuedDir !== opposite[currentDirectionRef.current]) {
          nextDir = queuedDir;
          break;
        }
      }
      currentDirectionRef.current = nextDir;
      setDirection(nextDir);

      setSnake(prev => {
        const head = prev[0];
        let newHead: Position;
        switch (nextDir) {
          case 'up': newHead = { x: head.x, y: head.y - 1 }; break;
          case 'down': newHead = { x: head.x, y: head.y + 1 }; break;
          case 'left': newHead = { x: head.x - 1, y: head.y }; break;
          case 'right': newHead = { x: head.x + 1, y: head.y }; break;
        }

        if (newHead.x < 0 || newHead.x >= GRID_SIZE || newHead.y < 0 || newHead.y >= GRID_SIZE) {
          setGameOver(true);
          playSound('error');
          return prev;
        }
        if (prev.some(s => s.x === newHead.x && s.y === newHead.y)) {
          setGameOver(true);
          playSound('error');
          return prev;
        }

        const newSnake = [newHead, ...prev];
        if (newHead.x === food.x && newHead.y === food.y) {
          playSound('success');
          setScore(s => {
            const newScore = Math.min(s + 10, MAX_SCORE);
            if (newScore >= MAX_SCORE) setShowGlitchCrash(true);
            if (newScore > highScore) {
              setHighScore(newScore);
              localStorage.setItem(HIGHSCORE_KEY, newScore.toString());
            }
            return newScore;
          });
          const newFood = spawnFood(newSnake);
          if (newFood === null) setTimeout(() => resetSnakeKeepScore(), 500);
          else setFood(newFood);
          return newSnake;
        }
        newSnake.pop();
        return newSnake;
      });
    }, TICK_SPEED);

    return () => clearInterval(interval);
  }, [gameStarted, gameOver, gameComplete, isPaused, food, highScore, playSound, spawnFood, resetSnakeKeepScore]);

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (!gameStarted) return;
      let newDir: Direction | null = null;
      switch (e.key) {
        case 'ArrowUp': case 'w': e.preventDefault(); newDir = 'up'; break;
        case 'ArrowDown': case 's': e.preventDefault(); newDir = 'down'; break;
        case 'ArrowLeft': case 'a': e.preventDefault(); newDir = 'left'; break;
        case 'ArrowRight': case 'd': e.preventDefault(); newDir = 'right'; break;
        case 'p': e.preventDefault(); if (!gameOver && !gameComplete) setIsPaused(p => !p); return;
      }
      if (newDir && directionQueueRef.current.length < 3) directionQueueRef.current.push(newDir);
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [gameStarted, gameOver, gameComplete]);

  const renderGrid = () => {
    const cells = [];
    const snakeSet = new Set(snake.map(s => `${s.x},${s.y}`));
    const head = snake[0];
    for (let y = 0; y < GRID_SIZE; y++) {
      for (let x = 0; x < GRID_SIZE; x++) {
        const isSnake = snakeSet.has(`${x},${y}`);
        const isHead = head.x === x && head.y === y;
        const isFood = food.x === x && food.y === y;
        cells.push(
          <div
            key={`${x}-${y}`}
            className={`flex items-center justify-center border transition-colors duration-75 ${
              isHead ? 'bg-primary box-glow border-primary'
                : isSnake ? 'bg-primary/80 border-primary/60'
                : isFood ? 'bg-destructive/80 border-destructive/60'
                : 'bg-background/50 border-primary/10'
            }`}
            style={{ width: cellSize, height: cellSize }}
          >
            {isFood && <div className="bg-destructive rounded-sm animate-pulse" style={{ width: cellSize * 0.5, height: cellSize * 0.5 }} />}
          </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'}`}
    >
      {/* Header */}
      <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">Snake</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>

      {/* Main layout */}
      <div className={`flex ${isMobile ? 'flex-col items-center' : 'flex-row gap-4'} flex-1 ${isFullscreen ? 'justify-center items-center' : ''}`}>
        {/* Game Grid */}
        <div className="border-2 border-primary box-glow p-1 bg-background/80">
          <div className="grid" style={{ gridTemplateColumns: `repeat(${GRID_SIZE}, ${cellSize}px)` }}>{renderGrid()}</div>
        </div>

        {/* Side Panel */}
        {!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">LENGTH</p>
              <p className="font-minecraft text-lg text-primary text-glow">{snake.length}</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">← → ↑ ↓ / WASD</p>
              <p className="font-pixel text-[10px] text-foreground/80">P: Pause</p>
            </div>
            {!gameStarted || gameOver || gameComplete ? (
              <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">
                {gameComplete ? 'PERFECT!' : 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>
        )}

        {/* Mobile Controls */}
        {isMobile && (
          <>
            <MobileControlsSpacer />
            <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">LEN</p><p className="font-minecraft text-sm text-primary">{snake.length}</p></div>
                </div>

                {gameStarted && !gameOver && !gameComplete ? (
                  <div className="grid grid-cols-3 gap-1 mt-2">
                    <div />
                    <GameTouchButton onAction={() => directionQueueRef.current.push('up')} className="p-4 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg">↑</GameTouchButton>
                    <div />
                    <GameTouchButton onAction={() => directionQueueRef.current.push('left')} className="p-4 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg">←</GameTouchButton>
                    <button onClick={() => setIsPaused(p => !p)} className="p-4 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-[10px] select-none">{isPaused ? '▶' : '❚❚'}</button>
                    <GameTouchButton onAction={() => directionQueueRef.current.push('right')} className="p-4 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg">→</GameTouchButton>
                    <div />
                    <GameTouchButton onAction={() => directionQueueRef.current.push('down')} className="p-4 border border-primary/50 active:bg-primary/40 text-primary font-pixel text-lg">↓</GameTouchButton>
                    <div />
                  </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>

      {/* Desktop Overlay */}
      {!isMobile && (gameOver || isPaused || gameComplete) && 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">{gameComplete ? 'GAME COMPLETE!' : gameOver ? 'GAME OVER' : 'PAUSED'}</h2>
            {(gameOver || gameComplete) && (
              <>
                <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">Length: {snake.length}</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 Snake;
