import React, { useState, useEffect, useRef } from 'react';
import { GridCell, Position, GameState, Direction } from '../types';
import { generateGrid, GRID_SIZE } from '../utils/gameLogic';
import { Cell } from './Cell';
import { RotateCcw, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, CircleHelp, BrickWall, Zap, Flag } from 'lucide-react';

const MOVE_INTERVAL_MS = 100; // Speed of movement when holding key

export const Game: React.FC = () => {
  const [grid, setGrid] = useState<GridCell[][]>([]);
  const [playerPos, setPlayerPos] = useState<Position>({ x: 0, y: 0 });
  const [gameState, setGameState] = useState<GameState>(GameState.PLAYING);
  const [moves, setMoves] = useState(0);
  const [trapsTriggered, setTrapsTriggered] = useState(0);

  // Refs for smooth movement loop and instant state access
  const gridRef = useRef<GridCell[][]>([]);
  const playerPosRef = useRef<Position>({ x: 0, y: 0 });
  const activeDirectionRef = useRef<Direction | null>(null);
  const lastMoveTimeRef = useRef<number>(0);
  const requestRef = useRef<number>();
  const gameStateRef = useRef<GameState>(GameState.PLAYING);

  // Sync refs with state whenever state updates
  useEffect(() => { gridRef.current = grid; }, [grid]);
  useEffect(() => { playerPosRef.current = playerPos; }, [playerPos]);
  useEffect(() => { gameStateRef.current = gameState; }, [gameState]);

  // Initialize game
  useEffect(() => {
    startNewGame();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const startNewGame = () => {
    const newGrid = generateGrid();
    setGrid(newGrid);
    gridRef.current = newGrid;
    
    const startPos = { x: 0, y: 0 };
    setPlayerPos(startPos);
    playerPosRef.current = startPos;
    
    setGameState(GameState.PLAYING);
    gameStateRef.current = GameState.PLAYING;
    
    setMoves(0);
    setTrapsTriggered(0);
    activeDirectionRef.current = null;
  };

  const handleInteraction = (direction: Direction) => {
    // Access latest state directly via refs
    const currentGrid = gridRef.current;
    const currentPos = playerPosRef.current;

    if (!currentGrid.length || gameStateRef.current !== GameState.PLAYING) return;

    let nextX = currentPos.x;
    let nextY = currentPos.y;

    switch (direction) {
      case Direction.UP: nextY -= 1; break;
      case Direction.DOWN: nextY += 1; break;
      case Direction.LEFT: nextX -= 1; break;
      case Direction.RIGHT: nextX += 1; break;
    }

    // 1. Boundary Check
    if (nextX < 0 || nextX >= GRID_SIZE || nextY < 0 || nextY >= GRID_SIZE) {
      return; // Hit grid edge
    }

    // 2. Interaction Logic
    // Create a deep copy of the grid to ensure immutability
    const newGrid = currentGrid.map(row => row.map(cell => ({ ...cell })));
    const targetCell = newGrid[nextY][nextX];
    const targetType = targetCell.type;
    
    let gridChanged = false;
    let newPos = currentPos;

    // Reveal the cell
    if (!targetCell.revealed) {
        targetCell.revealed = true;
        gridChanged = true;
    }

    if (targetType === 'wall') {
        // Blocked: Do not move, but wall is revealed
    } else if (targetType === 'trap') {
        // Trap: Reset to start
        setTrapsTriggered(t => t + 1);
        newPos = { x: 0, y: 0 };
    } else {
        // Safe / Start / End
        newPos = { x: nextX, y: nextY };
        targetCell.steppedOn = true;
        gridChanged = true;

        if (targetType === 'end') {
            setGameState(GameState.WON);
        }
    }

    // Update States
    if (gridChanged) {
        setGrid(newGrid);
    }
    
    if (newPos.x !== currentPos.x || newPos.y !== currentPos.y) {
        setPlayerPos(newPos);
        setMoves(m => m + 1);
    } else if (targetType === 'trap') {
        // Ensure visual reset even if we were somehow already at 0,0
        setPlayerPos({ x: 0, y: 0 });
    }
  };

  // Game Loop
  const animate = (time: number) => {
    if (activeDirectionRef.current && gameStateRef.current === GameState.PLAYING) {
      if (time - lastMoveTimeRef.current > MOVE_INTERVAL_MS) {
        handleInteraction(activeDirectionRef.current);
        lastMoveTimeRef.current = time;
      }
    }
    requestRef.current = requestAnimationFrame(animate);
  };

  useEffect(() => {
    requestRef.current = requestAnimationFrame(animate);
    return () => {
      if (requestRef.current) cancelAnimationFrame(requestRef.current);
    };
  }, []);

  // Key Listeners
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
        if (gameStateRef.current !== GameState.PLAYING) return;
        
        let dir: Direction | null = null;
        switch (e.key) {
          case 'ArrowUp': case 'w': case 'W': dir = Direction.UP; break;
          case 'ArrowDown': case 's': case 'S': dir = Direction.DOWN; break;
          case 'ArrowLeft': case 'a': case 'A': dir = Direction.LEFT; break;
          case 'ArrowRight': case 'd': case 'D': dir = Direction.RIGHT; break;
        }

        if (dir) {
            e.preventDefault(); // Prevent scrolling
            if (activeDirectionRef.current !== dir) {
                // Initial immediate move on press
                activeDirectionRef.current = dir;
                handleInteraction(dir);
                lastMoveTimeRef.current = performance.now();
            }
        }
    };

    const handleKeyUp = (e: KeyboardEvent) => {
        activeDirectionRef.current = null;
    };

    window.addEventListener('keydown', handleKeyDown);
    window.addEventListener('keyup', handleKeyUp);

    return () => {
      window.removeEventListener('keydown', handleKeyDown);
      window.removeEventListener('keyup', handleKeyUp);
    };
  }, []);


  return (
    <div className="flex flex-col items-center justify-center min-h-screen p-4 bg-gray-950">
      
      {/* Header */}
      <header className="mb-4 flex flex-col items-center gap-2">
        <h1 className="text-3xl font-bold text-blue-400 tracking-wider">GRID EXPLORER</h1>
        <div className="flex gap-6 text-sm text-gray-400 bg-gray-900/50 px-6 py-2 rounded-full border border-gray-800">
           <div className="flex items-center gap-2">
               <span className="text-gray-500">Moves:</span> 
               <span className="text-white font-mono">{moves}</span>
           </div>
           <div className="flex items-center gap-2">
               <span className="text-red-500/70">Traps:</span> 
               <span className="text-white font-mono">{trapsTriggered}</span>
           </div>
        </div>
      </header>

      {/* Main Game Area */}
      <div className="relative p-1 bg-gray-800 rounded-lg shadow-2xl shadow-black border border-gray-700">
        
        {/* Overlay for Win State */}
        {gameState === GameState.WON && (
          <div className="absolute inset-0 z-50 flex flex-col items-center justify-center bg-black/80 rounded-lg backdrop-blur-sm animate-in fade-in duration-500">
            <h2 className="text-5xl font-bold text-yellow-400 mb-4 drop-shadow-[0_0_15px_rgba(250,204,21,0.6)]">VICTORY!</h2>
            <p className="text-gray-300 mb-6">You reached the goal in {moves} moves.</p>
            <button 
              onClick={startNewGame}
              className="px-8 py-3 bg-blue-600 hover:bg-blue-500 text-white rounded-full font-bold transition-transform hover:scale-105 active:scale-95 shadow-lg shadow-blue-500/30"
            >
              Play Again
            </button>
          </div>
        )}

        {/* The Grid */}
        <div 
            className="grid gap-[1px] bg-gray-900 border-2 border-gray-900" 
            style={{ 
                gridTemplateColumns: `repeat(${GRID_SIZE}, minmax(0, 1fr))`,
                width: 'min(90vw, 600px)',
                height: 'min(90vw, 600px)'
            }}
        >
          {grid.map((row, y) => (
            row.map((cell, x) => (
              <Cell 
                key={`${x}-${y}`} 
                cell={cell} 
                isPlayerHere={playerPos.x === x && playerPos.y === y} 
              />
            ))
          ))}
        </div>
      </div>

      {/* Controls / Legend */}
      <div className="mt-8 grid grid-cols-1 md:grid-cols-2 gap-8 w-full max-w-2xl">
        
        {/* Legend */}
        <div className="bg-gray-900 p-4 rounded-xl border border-gray-800">
            <h3 className="text-gray-500 text-xs uppercase font-bold mb-3 tracking-widest">Legend</h3>
            <div className="grid grid-cols-2 gap-3 text-sm">
                <div className="flex items-center gap-2">
                    <div className="w-4 h-4 bg-gray-600 border border-gray-500 rounded-sm"></div>
                    <span className="text-gray-400">Safe Path</span>
                </div>
                <div className="flex items-center gap-2">
                    <div className="w-4 h-4 bg-slate-800 border border-slate-700 rounded-sm flex items-center justify-center"><BrickWall size={10} className="text-gray-600"/></div>
                    <span className="text-gray-400">Wall (Block)</span>
                </div>
                <div className="flex items-center gap-2">
                    <div className="w-4 h-4 bg-red-900 border border-red-800 rounded-sm flex items-center justify-center"><Zap size={10} className="text-red-500"/></div>
                    <span className="text-gray-400">Trap (Reset)</span>
                </div>
                <div className="flex items-center gap-2">
                    <div className="w-4 h-4 bg-yellow-900 border border-yellow-800 rounded-sm flex items-center justify-center"><Flag size={10} className="text-yellow-500"/></div>
                    <span className="text-gray-400">Goal</span>
                </div>
            </div>
        </div>

        {/* Instructions */}
        <div className="bg-gray-900 p-4 rounded-xl border border-gray-800 flex flex-col justify-between">
            <h3 className="text-gray-500 text-xs uppercase font-bold mb-3 tracking-widest flex items-center gap-2">
                <CircleHelp size={14} /> Instructions
            </h3>
            <p className="text-sm text-gray-400 leading-relaxed">
                Use <span className="text-blue-400 font-bold">Arrow Keys</span> or <span className="text-blue-400 font-bold">WASD</span> to move. 
                <br/>
                Hold key to move continuously.
                <br/>
                Avoid hidden traps!
            </p>
            <button 
                onClick={startNewGame}
                className="mt-4 w-full py-2 bg-gray-800 hover:bg-gray-700 text-gray-300 rounded-lg flex items-center justify-center gap-2 text-sm transition-colors border border-gray-700"
            >
                <RotateCcw size={14} /> Restart Map
            </button>
        </div>
      </div>
      
      {/* Mobile Controls (Optional, keeping it subtle) */}
      <div className="md:hidden mt-6 grid grid-cols-3 gap-2">
         <div />
         <button 
            onTouchStart={(e) => { e.preventDefault(); activeDirectionRef.current = Direction.UP; handleInteraction(Direction.UP); lastMoveTimeRef.current = performance.now(); }}
            onTouchEnd={(e) => { e.preventDefault(); activeDirectionRef.current = null; }}
            className="w-14 h-14 bg-gray-800 rounded-full flex items-center justify-center active:bg-blue-600 transition-colors"
         >
             <ArrowUp className="text-white" />
         </button>
         <div />
         <button 
            onTouchStart={(e) => { e.preventDefault(); activeDirectionRef.current = Direction.LEFT; handleInteraction(Direction.LEFT); lastMoveTimeRef.current = performance.now(); }}
            onTouchEnd={(e) => { e.preventDefault(); activeDirectionRef.current = null; }}
            className="w-14 h-14 bg-gray-800 rounded-full flex items-center justify-center active:bg-blue-600 transition-colors"
         >
             <ArrowLeft className="text-white" />
         </button>
         <button 
            onTouchStart={(e) => { e.preventDefault(); activeDirectionRef.current = Direction.DOWN; handleInteraction(Direction.DOWN); lastMoveTimeRef.current = performance.now(); }}
            onTouchEnd={(e) => { e.preventDefault(); activeDirectionRef.current = null; }}
            className="w-14 h-14 bg-gray-800 rounded-full flex items-center justify-center active:bg-blue-600 transition-colors"
         >
             <ArrowDown className="text-white" />
         </button>
         <button 
            onTouchStart={(e) => { e.preventDefault(); activeDirectionRef.current = Direction.RIGHT; handleInteraction(Direction.RIGHT); lastMoveTimeRef.current = performance.now(); }}
            onTouchEnd={(e) => { e.preventDefault(); activeDirectionRef.current = null; }}
            className="w-14 h-14 bg-gray-800 rounded-full flex items-center justify-center active:bg-blue-600 transition-colors"
         >
             <ArrowRight className="text-white" />
         </button>
      </div>

    </div>
  );
};