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

const GRID_SIZE = 20;
const TICK_SPEED = 120;

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

interface Player {
  snake: Position[];
  direction: Direction;
  score: number;
  alive: boolean;
  color: string;
  name: string;
}

const SnakeMultiplayer = () => {
  const { playSound } = useSettings();
  const [players, setPlayers] = useState<[Player, Player]>([
    { snake: [{ x: 5, y: 10 }], direction: 'right', score: 0, alive: true, color: 'hsl(var(--primary))', name: 'P1' },
    { snake: [{ x: 15, y: 10 }], direction: 'left', score: 0, alive: true, color: 'hsl(280 70% 50%)', name: 'P2' },
  ]);
  const [food, setFood] = useState<Position>({ x: 10, y: 10 });
  const [gameOver, setGameOver] = useState(false);
  const [winner, setWinner] = useState<string | null>(null);
  const [gameStarted, setGameStarted] = useState(false);
  const [isPaused, setIsPaused] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const gameRef = useRef<HTMLDivElement>(null);
  
  const directionQueues = useRef<[Direction[], Direction[]]>([[], []]);
  const currentDirections = useRef<[Direction, Direction]>(['right', 'left']);

  const { enterFullscreen, exitFullscreen } = useBrowserFullscreen();

  const getCellSize = useCallback(() => {
    if (typeof window === 'undefined') return 20;
    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), 16);
    }
    return isFullscreen ? 24 : 20;
  }, [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]);

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

  const spawnFood = useCallback((snakes: Position[][]): Position => {
    const occupied = new Set(snakes.flat().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 { x: 10, y: 10 };
    return available[Math.floor(Math.random() * available.length)];
  }, []);

  const startGame = () => {
    const p1Start = [{ x: 5, y: 10 }];
    const p2Start = [{ x: 15, y: 10 }];
    setPlayers([
      { snake: p1Start, direction: 'right', score: 0, alive: true, color: 'hsl(var(--primary))', name: 'P1' },
      { snake: p2Start, direction: 'left', score: 0, alive: true, color: 'hsl(280 70% 50%)', name: 'P2' },
    ]);
    currentDirections.current = ['right', 'left'];
    directionQueues.current = [[], []];
    setFood(spawnFood([p1Start, p2Start]));
    setGameOver(false);
    setWinner(null);
    setIsPaused(false);
    setGameStarted(true);
    playSound('success');
    gameRef.current?.focus();
  };

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

    const interval = setInterval(() => {
      const opposite: Record<Direction, Direction> = { up: 'down', down: 'up', left: 'right', right: 'left' };
      
      setPlayers(prev => {
        const newPlayers: [Player, Player] = [{ ...prev[0] }, { ...prev[1] }];
        
        for (let i = 0; i < 2; i++) {
          if (!newPlayers[i].alive) continue;
          
          // Process direction queue
          let nextDir = currentDirections.current[i];
          while (directionQueues.current[i].length > 0) {
            const queuedDir = directionQueues.current[i].shift()!;
            if (queuedDir !== opposite[currentDirections.current[i]]) {
              nextDir = queuedDir;
              break;
            }
          }
          currentDirections.current[i] = nextDir;
          newPlayers[i].direction = nextDir;
          
          // Move snake
          const head = newPlayers[i].snake[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;
          }
          
          // Check wall collision
          if (newHead.x < 0 || newHead.x >= GRID_SIZE || newHead.y < 0 || newHead.y >= GRID_SIZE) {
            newPlayers[i].alive = false;
            playSound('error');
            continue;
          }
          
          // Check self collision
          if (newPlayers[i].snake.some(s => s.x === newHead.x && s.y === newHead.y)) {
            newPlayers[i].alive = false;
            playSound('error');
            continue;
          }
          
          // Check collision with other snake
          const otherIndex = i === 0 ? 1 : 0;
          if (newPlayers[otherIndex].snake.some(s => s.x === newHead.x && s.y === newHead.y)) {
            newPlayers[i].alive = false;
            playSound('error');
            continue;
          }
          
          const newSnake = [newHead, ...newPlayers[i].snake];
          
          // Check food
          if (newHead.x === food.x && newHead.y === food.y) {
            playSound('success');
            newPlayers[i].score += 10;
            setFood(spawnFood([newPlayers[0].snake, newPlayers[1].snake]));
          } else {
            newSnake.pop();
          }
          
          newPlayers[i].snake = newSnake;
        }
        
        // Check win condition
        const alive = newPlayers.filter(p => p.alive);
        if (alive.length === 0) {
          setGameOver(true);
          setWinner('Draw!');
        } else if (alive.length === 1) {
          setGameOver(true);
          setWinner(`${alive[0].name} Wins!`);
        }
        
        return newPlayers;
      });
    }, TICK_SPEED);

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

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (!gameStarted) return;
      
      // Player 1: WASD
      if (e.key === 'w' || e.key === 'W') { e.preventDefault(); if (directionQueues.current[0].length < 3) directionQueues.current[0].push('up'); }
      if (e.key === 's' || e.key === 'S') { e.preventDefault(); if (directionQueues.current[0].length < 3) directionQueues.current[0].push('down'); }
      if (e.key === 'a' || e.key === 'A') { e.preventDefault(); if (directionQueues.current[0].length < 3) directionQueues.current[0].push('left'); }
      if (e.key === 'd' || e.key === 'D') { e.preventDefault(); if (directionQueues.current[0].length < 3) directionQueues.current[0].push('right'); }
      
      // Player 2: Arrow keys
      if (e.key === 'ArrowUp') { e.preventDefault(); if (directionQueues.current[1].length < 3) directionQueues.current[1].push('up'); }
      if (e.key === 'ArrowDown') { e.preventDefault(); if (directionQueues.current[1].length < 3) directionQueues.current[1].push('down'); }
      if (e.key === 'ArrowLeft') { e.preventDefault(); if (directionQueues.current[1].length < 3) directionQueues.current[1].push('left'); }
      if (e.key === 'ArrowRight') { e.preventDefault(); if (directionQueues.current[1].length < 3) directionQueues.current[1].push('right'); }
      
      if (e.key === 'p' || e.key === 'P') { e.preventDefault(); if (!gameOver) setIsPaused(p => !p); }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [gameStarted, gameOver]);

  const renderGrid = () => {
    const cells = [];
    const p1Set = new Set(players[0].snake.map(s => `${s.x},${s.y}`));
    const p2Set = new Set(players[1].snake.map(s => `${s.x},${s.y}`));
    const p1Head = players[0].snake[0];
    const p2Head = players[1].snake[0];
    
    for (let y = 0; y < GRID_SIZE; y++) {
      for (let x = 0; x < GRID_SIZE; x++) {
        const isP1 = p1Set.has(`${x},${y}`);
        const isP2 = p2Set.has(`${x},${y}`);
        const isP1Head = p1Head.x === x && p1Head.y === y && players[0].alive;
        const isP2Head = p2Head.x === x && p2Head.y === y && players[1].alive;
        const isFood = food.x === x && food.y === y;
        
        let bgClass = 'bg-background/50 border-primary/10';
        let style: React.CSSProperties = { width: cellSize, height: cellSize };
        
        if (isP1Head) {
          bgClass = 'border-primary';
          style.backgroundColor = players[0].color;
          style.boxShadow = `0 0 10px ${players[0].color}`;
        } else if (isP1 && players[0].alive) {
          bgClass = 'border-primary/60';
          style.backgroundColor = players[0].color;
          style.opacity = 0.8;
        } else if (isP2Head) {
          bgClass = 'border-purple-500';
          style.backgroundColor = players[1].color;
          style.boxShadow = `0 0 10px ${players[1].color}`;
        } else if (isP2 && players[1].alive) {
          bgClass = 'border-purple-500/60';
          style.backgroundColor = players[1].color;
          style.opacity = 0.8;
        } else if (isFood) {
          bgClass = 'bg-destructive/80 border-destructive/60';
        }
        
        cells.push(
          <div
            key={`${x}-${y}`}
            className={`flex items-center justify-center border transition-colors duration-75 ${bgClass}`}
            style={style}
          >
            {isFood && <div className="bg-destructive rounded-sm animate-pulse" style={{ width: cellSize * 0.5, height: cellSize * 0.5 }} />}
          </div>
        );
      }
    }
    return cells;
  };

  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">Snake 2P</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">
          <div className="grid" style={{ gridTemplateColumns: `repeat(${GRID_SIZE}, ${cellSize}px)` }}>{renderGrid()}</div>
        </div>

        {!isMobile && (
          <div className="flex flex-col gap-2 min-w-[160px]">
            {/* Player 1 Stats */}
            <div className="border border-primary/50 p-3 bg-background/50">
              <div className="flex items-center gap-2 mb-1">
                <div className="w-3 h-3 rounded-sm" style={{ backgroundColor: players[0].color }} />
                <p className="font-pixel text-[10px] text-foreground/60">PLAYER 1 (WASD)</p>
              </div>
              <p className="font-minecraft text-lg text-primary text-glow">{players[0].score}</p>
              {!players[0].alive && <p className="font-pixel text-[8px] text-destructive">DEAD</p>}
            </div>

            {/* Player 2 Stats */}
            <div className="border border-purple-500/50 p-3 bg-background/50">
              <div className="flex items-center gap-2 mb-1">
                <div className="w-3 h-3 rounded-sm" style={{ backgroundColor: players[1].color }} />
                <p className="font-pixel text-[10px] text-foreground/60">PLAYER 2 (↑↓←→)</p>
              </div>
              <p className="font-minecraft text-lg text-purple-400">{players[1].score}</p>
              {!players[1].alive && <p className="font-pixel text-[8px] text-destructive">DEAD</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-[9px] text-primary">P1: W A S D</p>
              <p className="font-pixel text-[9px] text-purple-400">P2: ↑ ↓ ← →</p>
              <p className="font-pixel text-[9px] text-foreground/80 mt-1">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 ? 'PLAY AGAIN' : '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 />
            <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">P1</p><p className="font-minecraft text-sm text-primary">{players[0].score}</p></div>
                  <div><p className="font-pixel text-[8px] text-foreground/60">P2</p><p className="font-minecraft text-sm text-purple-400">{players[1].score}</p></div>
                </div>

                {!gameStarted || gameOver ? (
                  <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 ? 'PLAY AGAIN' : 'START'}
                  </button>
                ) : (
                  <button onClick={() => setIsPaused(p => !p)} 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">
                    {isPaused ? 'RESUME' : 'PAUSE'}
                  </button>
                )}

                <div className="flex gap-3 font-pixel text-[10px] text-foreground/70">
                  <span className="text-primary">P1: WASD</span>
                  <span className="text-purple-400">P2: ↑↓←→</span>
                </div>
              </div>
            </MobileControlsDock>
          </>
        )}
      </div>

      {/* Game Over / Pause Overlay */}
      {(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 ? winner : 'PAUSED'}
            </h2>
            {gameOver && (
              <div className="flex gap-4 justify-center mb-3">
                <div>
                  <p className="font-pixel text-[10px] text-foreground/60">P1 Score</p>
                  <p className="font-minecraft text-lg text-primary">{players[0].score}</p>
                </div>
                <div>
                  <p className="font-pixel text-[10px] text-foreground/60">P2 Score</p>
                  <p className="font-minecraft text-lg text-purple-400">{players[1].score}</p>
                </div>
              </div>
            )}
            <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 SnakeMultiplayer;