/// <reference path="../react-app-env.d.ts" />
import * as React from 'react';
const { useState, useEffect } = React;
import { getGameState, makeMove, getHint } from '../services/api';
import { playSound, preloadSounds } from '../services/soundService';
import ChessClock from './ChessClock';

interface ChessBoardProps {
  theme: 'brown' | 'grey';
}

interface Piece {
  type: string;
  color: 'white' | 'black';
  position: string;
}

interface HighlightedSquare {
  square: string;
  type: 'selected' | 'hint' | 'legal-move';
}

const ChessBoard: React.FC<ChessBoardProps> = ({ theme }) => {
  const [fen, setFen] = useState<string>('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
  const [pieces, setPieces] = useState<Piece[]>([]);
  const [selectedPiece, setSelectedPiece] = useState<string | null>(null);
  const [legalMoves, setLegalMoves] = useState<string[]>([]);
  const [highlightedSquares, setHighlightedSquares] = useState<HighlightedSquare[]>([]);
  const [hintMove, setHintMove] = useState<{ from: string; to: string } | null>(null);
  const [isPlayerTurn, setIsPlayerTurn] = useState<boolean>(true);
  const [playerColor, setPlayerColor] = useState<'white' | 'black'>('white');
  const [lastMove, setLastMove] = useState<{ from: string; to: string } | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [moveInProgress, setMoveInProgress] = useState<boolean>(false);
  const [statusMessage, setStatusMessage] = useState<string>('');
  const [gameStarted, setGameStarted] = useState<boolean>(false);
  const [lastPlayerMove, setLastPlayerMove] = useState<{ from: string; to: string } | null>(null);
  const [lastAiMove, setLastAiMove] = useState<{ from: string; to: string } | null>(null);

  // Initialize the board and preload sounds
  useEffect(() => {
    fetchGameState();
    preloadSounds(); // Preload sound effects
  }, []);

  // Parse FEN and update pieces
  useEffect(() => {
    if (fen) {
      const parsedPieces = parseFen(fen);
      setPieces(parsedPieces);
    }
  }, [fen]);

  const fetchGameState = async () => {
    try {
      console.log('Fetching game state...');
      const response = await getGameState();
      console.log('Game state response:', response);
      
      setFen(response.board_state.fen);
      setLegalMoves(response.board_state.legal_moves);
      setIsPlayerTurn(response.board_state.turn === (response.player_color || 'white'));
      if (response.player_color) {
        setPlayerColor(response.player_color);
      }
      
      // Check if game has started (move count > 0 or legal moves available)
      setGameStarted(response.board_state.move_count > 0 || response.board_state.legal_moves.length > 0);
    } catch (error) {
      console.error('Error fetching game state:', error);
      console.error('Error details:', error.response?.data || error.message);
      setStatusMessage(`Connection error: ${error.response?.status || 'Server not responding'}`);
    }
  };

  const parseFen = (fenString: string): Piece[] => {
    const pieces: Piece[] = [];
    const fenParts = fenString.split(' ');
    const ranks = fenParts[0].split('/');
    
    ranks.forEach((rank, rankIndex) => {
      let fileIndex = 0;
      
      for (let i = 0; i < rank.length; i++) {
        const char = rank[i];
        
        if (!isNaN(parseInt(char))) {
          fileIndex += parseInt(char);
        } else {
          const color = char === char.toUpperCase() ? 'white' : 'black';
          const type = char.toLowerCase();
          const position = String.fromCharCode(97 + fileIndex) + (8 - rankIndex);
          
          pieces.push({
            type,
            color,
            position,
          });
          
          fileIndex++;
        }
      }
    });
    
    return pieces;
  };

  const handleSquareClick = async (square: string) => {
    // Check if game has started
    if (!gameStarted) {
      setStatusMessage('Please start a new game first');
      return;
    }
    
    // If a hint is active and the clicked square is the hint destination
    if (hintMove && square === hintMove.to) {
      await handleMove(hintMove.from, hintMove.to);
      setHintMove(null);
      return;
    }

    // Find if there's a piece on the clicked square
    const pieceOnSquare = pieces.find((p: Piece) => p.position === square);
    
    // If a piece is already selected
    if (selectedPiece) {
      // Check if the clicked square is a legal move
      const move = `${selectedPiece}${square}`;
      const isLegalMove = legalMoves.some((m: string) => m === move);
      
      if (isLegalMove) {
        await handleMove(selectedPiece, square);
      }
      
      // Clear selection
      setSelectedPiece(null);
      setHighlightedSquares([]);
    } 
    // If clicking on a piece of the player's color
    else if (pieceOnSquare && pieceOnSquare.color === (isPlayerTurn ? playerColor : (playerColor === 'white' ? 'black' : 'white'))) {
      setSelectedPiece(square);
      
      // Highlight legal moves for this piece
      const legalMovesForPiece = legalMoves
        .filter((move: string) => move.startsWith(square))
        .map((move: string) => move.substring(2));
      
      const highlights: HighlightedSquare[] = [
        { square, type: 'selected' },
        ...legalMovesForPiece.map((move: string) => ({ square: move, type: 'legal-move' })),
      ];
      
      setHighlightedSquares(highlights);
    }
  };

  const handleMove = async (from: string, to: string) => {
    try {
      console.log(`Attempting to make move: ${from} to ${to}`);
      
      // IMMEDIATELY switch to AI's turn when player commits to a move
      // This stops the player's clock and starts the AI's clock
      setIsPlayerTurn(false);
      console.log('Player move committed - switched to AI turn');
      
      // Set loading state and update status message
      setMoveInProgress(true);
      setStatusMessage('Processing move...');
      
      // IMMEDIATELY update the UI for the player's move (optimistic update)
      // Find the piece being moved
      const movingPiece = pieces.find(p => p.position === from);
      const targetPiece = pieces.find(p => p.position === to);
      
      if (movingPiece) {
        // Create a new pieces array with the updated position
        const updatedPieces = pieces.map(p => {
          if (p.position === from) {
            return { ...p, position: to };
          }
          // Remove the captured piece if there is one
          if (p.position === to && p !== movingPiece) {
            return null;
          }
          return p;
        }).filter(Boolean) as Piece[];
        
        // Update the pieces state immediately for the player's move
        setPieces(updatedPieces);
        
        // Determine the type of move for sound effects
        const isCapture = targetPiece !== undefined;
        const isCastle = movingPiece.type === 'k' && 
          ((from === 'e1' && (to === 'g1' || to === 'c1')) || 
           (from === 'e8' && (to === 'g8' || to === 'c8')));
        
        // Play appropriate sound
        if (isCastle) {
          playSound('castle');
        } else if (isCapture) {
          playSound('capture');
        } else {
          playSound('move');
        }
      }
      
      // First highlight the squares for visual feedback
      setHighlightedSquares([
        { square: from, type: 'selected' },
        { square: to, type: 'selected' }
      ]);
      
      // Make the API call to process the move
      const moveNotation = `${from}${to}`;
      console.log(`Making API call with move: ${moveNotation}`);
      
      const response = await makeMove(moveNotation);
      console.log('API response:', response);
      
      if (response.status === 'success' || response.status === 'game_over') {
        // Check if the move puts the opponent in check
        const isCheck = response.board_state?.in_check;
        if (isCheck) {
          setTimeout(() => playSound('check'), 150);
          setStatusMessage('Check!');
        } else {
          setStatusMessage('');
        }
        
        // Check if game is over
        if (response.status === 'game_over') {
          setTimeout(() => playSound('game-end'), 300);
          setStatusMessage(response.result === 'draw' ? 'Game ended in a draw' : `${response.winner} wins!`);
        }
        
        // Store player's move first
        setLastPlayerMove({ from, to });
        setLastMove({ from, to });
        
        // Update the board state with the server response (but not the FEN yet if AI will move)
        setLegalMoves(response.board_state.legal_moves);
        
        // If AI made a move, handle the sequence properly
        if (response.ai_move) {
          const aiFrom = response.ai_move.substring(0, 2);
          const aiTo = response.ai_move.substring(2, 4);
          
          // AI's clock is already running since we switched turns at the start
          // Show AI move after a delay
          setTimeout(() => {
            // Store AI's last move
            setLastAiMove({ from: aiFrom, to: aiTo });
            
            // Update the board with AI's move
            setFen(response.board_state.fen);
            
            // Play sound for AI move
            const aiMovingPiece = pieces.find(p => p.position === aiFrom);
            const aiTargetPiece = pieces.find(p => p.position === aiTo);
            
            if (aiMovingPiece) {
              const isAiCapture = aiTargetPiece !== undefined;
              const isAiCastle = aiMovingPiece.type === 'k' && 
                ((aiFrom === 'e1' && (aiTo === 'g1' || aiTo === 'c1')) || 
                 (aiFrom === 'e8' && (aiTo === 'g8' || aiTo === 'c8')));
              
              if (isAiCastle) {
                playSound('castle');
              } else if (isAiCapture) {
                playSound('capture');
              } else {
                playSound('move');
              }
            }
            
            // After AI move is shown, switch back to player's turn
            setTimeout(() => {
              const finalPlayerTurn = response.board_state.turn === playerColor;
              setIsPlayerTurn(finalPlayerTurn);
              console.log(`Final turn update: ${finalPlayerTurn ? 'Player' : 'AI'} turn`);
            }, 200);
          }, 800); // Delay AI move display by 800ms
        } else {
          // No AI move, just update the board and turn
          setFen(response.board_state.fen);
          const newPlayerTurn = response.board_state.turn === playerColor;
          setIsPlayerTurn(newPlayerTurn);
          console.log(`Updated turn: board turn=${response.board_state.turn}, playerColor=${playerColor}, isPlayerTurn=${newPlayerTurn}`);
        }
        
        // Clear highlights after a short delay
        setTimeout(() => {
          setHighlightedSquares([]);
        }, 500);
      } else {
        // Clear highlights immediately if move failed
        setHighlightedSquares([]);
        setStatusMessage('Invalid move');
        
        // Reset pieces to match the FEN since our optimistic update was wrong
        setPieces(parseFen(fen));
      }
    } catch (error) {
      console.error('Error making move:', error);
      console.error('Error details:', error.response?.data || error.message);
      setHighlightedSquares([]);
      setStatusMessage(`Error making move: ${error.response?.data?.message || error.message}`);
      
      // Reset pieces to match the FEN since our optimistic update was wrong
      setPieces(parseFen(fen));
      
      // Reset player turn on error
      setIsPlayerTurn(true);
    } finally {
      setMoveInProgress(false);
    }
  };

  const handleRequestHint = async () => {
    try {
      const response = await getHint();
      if (response.status === 'success') {
        const hint = response.hint;
        const from = hint.substring(0, 2);
        const to = hint.substring(2, 4);
        
        setHintMove({ from, to });
        setHighlightedSquares([
          { square: from, type: 'hint' },
          { square: to, type: 'hint' },
        ]);
      }
    } catch (error) {
      console.error('Error getting hint:', error);
    }
  };

  const renderSquare = (square: string, isLight: boolean) => {
    const piece = pieces.find(p => p.position === square);
    
    const isHighlighted = highlightedSquares.find(h => h.square === square);
    const isLastMoveFrom = lastMove && lastMove.from === square;
    const isLastMoveTo = lastMove && lastMove.to === square;
    
    // Check for player and AI move highlights
    const isPlayerMoveFrom = lastPlayerMove && lastPlayerMove.from === square;
    const isPlayerMoveTo = lastPlayerMove && lastPlayerMove.to === square;
    const isAiMoveFrom = lastAiMove && lastAiMove.from === square;
    const isAiMoveTo = lastAiMove && lastAiMove.to === square;
    
    const squareColor = isLight ? 'light' : 'dark';
    const boardColor = 'brown';
    const colorInFilename = 'brown';
    
    const imageUrl = `/assets/boards/${boardColor}/square ${colorInFilename} ${squareColor}_1x.png`;
    
    return (
      <div 
        key={square}
        className={`chess-square ${isLight ? 'bg-board-light' : 'bg-board-dark'} ${isLight ? 'light-square' : 'dark-square'}`}
        style={{
          backgroundImage: `url(${imageUrl})`,
          backgroundSize: 'cover',
          backgroundColor: isLight ? '#f0d9b5' : '#b58863'
        }}
        data-high-res={`/assets/boards/${boardColor}/square ${colorInFilename} ${squareColor}_2x.png`}
        data-theme={theme}
        onClick={() => handleSquareClick(square)}
      >
        {isHighlighted && isHighlighted.type === 'selected' && (
          <div className="square-selected"></div>
        )}
        
        {isHighlighted && isHighlighted.type === 'hint' && (
          <div className="hint-square"></div>
        )}
        
        {isHighlighted && isHighlighted.type === 'legal-move' && (
          <div 
            className="move-dot"
            style={{
              position: 'absolute',
              top: '50%',
              left: '50%',
              transform: 'translate(-50%, -50%)',
              width: piece ? '80%' : '25%',  // Larger circle for capture moves
              height: piece ? '80%' : '25%', // Larger circle for capture moves
              borderRadius: '50%',
              backgroundColor: piece ? 'rgba(34, 197, 94, 0.3)' : 'rgba(34, 197, 94, 0.8)', // Different opacity for captures
              border: piece ? '3px solid rgba(34, 197, 94, 0.9)' : 'none', // Border for capture moves
              zIndex: piece ? 3 : 2, // Higher z-index for captures to show above pieces
              pointerEvents: 'none'
            }}
          />
        )}
        
        {/* Player move highlighting - light blue border */}
        {(isPlayerMoveFrom || isPlayerMoveTo) && (
          <div 
            className="player-move-highlight"
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              right: 0,
              bottom: 0,
              boxShadow: 'inset 0 0 0 4px rgba(0, 120, 255, 0.8)',
              zIndex: 1
            }}
          />
        )}
        
        {/* AI move highlighting - orange border */}
        {(isAiMoveFrom || isAiMoveTo) && (
          <div 
            className="ai-move-highlight"
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              right: 0,
              bottom: 0,
              boxShadow: 'inset 0 0 0 4px rgba(255, 165, 0, 0.8)',
              zIndex: 1
            }}
          />
        )}
        
        {piece && (
          <div 
            className={`${isLastMoveFrom || isLastMoveTo ? 'moving-piece' : ''}`}
            style={{
              backgroundImage: `url(/assets/pieces/${piece.color[0]}_${getPieceName(piece.type)}_1x.png)`,
              backgroundSize: 'contain',
              backgroundRepeat: 'no-repeat',
              backgroundPosition: 'center',
              width: '85%',
              height: '85%',
              transition: 'transform 0.2s',
              position: 'relative',
              zIndex: 2
            }}
            data-high-res={`/assets/pieces/${piece.color[0]}_${getPieceName(piece.type)}_2x.png`}
          />
        )}
      </div>
    );
  };

  const getPieceName = (type: string): string => {
    switch (type) {
      case 'p': return 'pawn';
      case 'r': return 'rook';
      case 'n': return 'knight';
      case 'b': return 'bishop';
      case 'q': return 'queen';
      case 'k': return 'king';
      default: return 'pawn';
    }
  };

  const renderBoard = () => {
    const squares = [];
    const files = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
    const ranks = ['8', '7', '6', '5', '4', '3', '2', '1'];
    
    // Flip the board if player is black
    const displayRanks = playerColor === 'white' ? ranks : [...ranks].reverse();
    const displayFiles = playerColor === 'white' ? files : [...files].reverse();
    
    for (let rankIndex = 0; rankIndex < 8; rankIndex++) {
      for (let fileIndex = 0; fileIndex < 8; fileIndex++) {
        const file = displayFiles[fileIndex];
        const rank = displayRanks[rankIndex];
        const square = file + rank;
        const isLight = (fileIndex + rankIndex) % 2 === 1;
        
        squares.push(renderSquare(square, isLight));
      }
    }
    
    return squares;
  };

  return (
    <div className="flex flex-col items-center">
      {/* Chess Clock */}
      <ChessClock 
        isPlayerTurn={isPlayerTurn}
        playerColor={playerColor}
        gameActive={gameStarted && !statusMessage.includes('wins') && !statusMessage.includes('draw')}
        initialTimeMinutes={10}
      />
      
      {/* Status message and turn indicator */}
      <div className="w-full max-w-[800px] mb-4 flex justify-between items-center text-gradio-text">
        <div className="text-2xl font-medium">
          {!gameStarted ? "Click 'New Game' to start playing" : (isPlayerTurn ? "Your turn" : "AI is thinking...")}
        </div>
        <div className={`text-2xl font-bold ${
          statusMessage.includes('Check') 
            ? 'text-gradio-red' 
            : statusMessage.includes('wins') 
              ? 'text-gradio-green' 
              : 'text-gradio-blue'
        }`}>
          {statusMessage}
        </div>
        {moveInProgress && (
          <div className="flex items-center">
            <div className="animate-spin rounded-full h-7 w-7 border-b-2 border-gradio-orange mr-2"></div>
            <span className="text-xl">Processing move...</span>
          </div>
        )}
      </div>
      
      {/* Chess board with external rank and file labels */}
      <div className="relative" style={{ width: '880px', maxWidth: '100%', margin: '0 auto', paddingBottom: '60px' }}>
        {/* Rank labels (1-8) */}
        <div className="absolute left-0 top-0 bottom-60px flex flex-col justify-around" style={{ width: '40px', height: '800px' }}>
          {playerColor === 'white' 
            ? ['8', '7', '6', '5', '4', '3', '2', '1'].map(rank => (
                <div key={rank} className="flex items-center justify-center text-2xl font-bold text-gradio-text">
                  {rank}
                </div>
              ))
            : ['1', '2', '3', '4', '5', '6', '7', '8'].map(rank => (
                <div key={rank} className="flex items-center justify-center text-2xl font-bold text-gradio-text">
                  {rank}
                </div>
              ))
          }
        </div>
        
        {/* Chess board with dark theme border */}
        <div 
          className="chess-board ml-10"
          style={{ 
            display: 'grid',
            gridTemplateColumns: 'repeat(8, 1fr)',
            gridTemplateRows: 'repeat(8, 1fr)',
            width: '800px',
            height: '800px',
            maxWidth: 'calc(100% - 40px)',
            boxShadow: '0 4px 15px -1px rgba(0, 0, 0, 0.5)',
            position: 'relative',
            border: '4px solid #374151',
            margin: '0 auto'
          }}
        >
          {renderBoard()}
          
          {/* Loading overlay */}
          {isLoading && (
            <div style={{
              position: 'absolute',
              inset: 0,
              backgroundColor: 'rgba(0, 0, 0, 0.5)',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              zIndex: 10
            }}>
              <div style={{
                backgroundColor: '#1f2937',
                padding: '1.5rem',
                borderRadius: '0.5rem',
                boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.3)',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                color: 'white'
              }}>
                <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-gradio-orange mb-3"></div>
                <p className="text-xl">Loading...</p>
              </div>
            </div>
          )}
        </div>
        
        {/* File labels (a-h) */}
        <div className="absolute left-10 top-[800px] right-0 flex justify-around" style={{ height: '50px' }}>
          {playerColor === 'white' 
            ? ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'].map(file => (
                <div key={file} className="flex items-center justify-center text-2xl font-bold text-gradio-text">
                  {file}
                </div>
              ))
            : ['h', 'g', 'f', 'e', 'd', 'c', 'b', 'a'].map(file => (
                <div key={file} className="flex items-center justify-center text-2xl font-bold text-gradio-text">
                  {file}
                </div>
              ))
          }
        </div>
      </div>
      
      {/* Hint button with full width */}
      <button 
        className="mt-20 w-[800px] max-w-full py-4 bg-gradio-green text-white rounded-lg hover:bg-green-500 transition-colors text-2xl font-medium disabled:bg-gray-400 disabled:cursor-not-allowed"
        onClick={handleRequestHint}
        disabled={moveInProgress || !isPlayerTurn || !gameStarted}
        style={{ margin: '0 auto' }}
      >
        Get Hint
      </button>
    </div>
  );
};

export default ChessBoard;