import { type ChessPiece, PieceType, PieceColor, type Position, type MoveResult, GameMode } from "./chess-types"
import { cloneBoard, findKingPosition } from "./chess-utils"

// Check if a move is valid for a specific piece
export function isValidMove(
  board: (ChessPiece | null)[][],
  from: Position,
  to: Position,
  currentPlayer: PieceColor,
  gameMode: GameMode = GameMode.CLASSIC,
): boolean {
  // Cannot move to the same position
  if (from.row === to.row && from.col === to.col) {
    return false
  }

  const piece = board[from.row][from.col]

  // No piece at the starting position or wrong player's piece
  if (!piece || piece.color !== currentPlayer) {
    return false
  }

  const targetPiece = board[to.row][to.col]

  // Cannot capture own piece
  if (targetPiece && targetPiece.color === piece.color) {
    return false
  }

  // Check piece-specific movement rules
  let validPieceMove = false

  switch (piece.type) {
    case PieceType.PAWN:
      validPieceMove = isValidPawnMove(board, from, to)
      break
    case PieceType.ROOK:
      validPieceMove = isValidRookMove(board, from, to)
      break
    case PieceType.KNIGHT:
      validPieceMove = isValidKnightMove(from, to)
      break
    case PieceType.BISHOP:
      validPieceMove = isValidBishopMove(board, from, to)
      break
    case PieceType.QUEEN:
      validPieceMove = isValidQueenMove(board, from, to)
      break
    case PieceType.KING:
      validPieceMove = isValidKingMove(board, from, to)
      break
  }

  if (!validPieceMove) {
    return false
  }

  // In ghost chess, forced captures take priority
  if (gameMode === GameMode.GHOST) {
    const captureMoves = getCaptureMoves(board, currentPlayer)
    const isCapture = targetPiece !== null
    
    // If there are capture moves available and this isn't a capture, it's invalid
    if (captureMoves.length > 0 && !isCapture) {
      return false
    }
  }

  // Check if the move would put or leave the king in check (only in classic mode)
  if (gameMode === GameMode.CLASSIC) {
    const newBoard = cloneBoard(board)
    newBoard[to.row][to.col] = newBoard[from.row][from.col]
    newBoard[from.row][from.col] = null

    return !isKingInCheck(newBoard, piece.color)
  }

  return true
}

// Make a move and return the new board state
export function makeMove(board: (ChessPiece | null)[][], from: Position, to: Position): MoveResult {
  const newBoard = cloneBoard(board)
  const piece = newBoard[from.row][from.col]
  const capturedPiece = newBoard[to.row][to.col]

  if (!piece) {
    return { newBoard, capturedPiece: null }
  }

  // Update hasMoved property for pawns, kings, and rooks (for castling)
  if (piece.type === PieceType.PAWN || piece.type === PieceType.KING || piece.type === PieceType.ROOK) {
    piece.hasMoved = true
  }

  // Handle pawn promotion
  if (piece.type === PieceType.PAWN && (to.row === 0 || to.row === 7)) {
    piece.type = PieceType.QUEEN // Auto-promote to queen for simplicity
  }

  // Handle castling
  if (piece.type === PieceType.KING && Math.abs(from.col - to.col) === 2) {
    const isKingSide = to.col > from.col
    const rookCol = isKingSide ? 7 : 0
    const newRookCol = isKingSide ? from.col + 1 : from.col - 1

    // Move the rook
    newBoard[from.row][newRookCol] = newBoard[from.row][rookCol]
    newBoard[from.row][rookCol] = null

    if (newBoard[from.row][newRookCol]) {
      newBoard[from.row][newRookCol]!.hasMoved = true
    }
  }

  // Make the move
  newBoard[to.row][to.col] = piece
  newBoard[from.row][from.col] = null

  return { newBoard, capturedPiece }
}

// Check if the king of the given color is in check
export function isCheck(board: (ChessPiece | null)[][], color: PieceColor): boolean {
  return isKingInCheck(board, color)
}

// Check if the king of the given color is in checkmate
export function isCheckmate(board: (ChessPiece | null)[][], color: PieceColor, gameMode: GameMode = GameMode.CLASSIC): boolean {
  // Ghost chess doesn't have checkmate
  if (gameMode === GameMode.GHOST) {
    return false
  }

  // If the king is not in check, it's not checkmate
  if (!isKingInCheck(board, color)) {
    return false
  }

  // Check if any move can get the king out of check
  return !hasLegalMoves(board, color, gameMode)
}

// Check if the position is a stalemate
export function isStalemate(board: (ChessPiece | null)[][], color: PieceColor, gameMode: GameMode = GameMode.CLASSIC): boolean {
  // Ghost chess doesn't have stalemate
  if (gameMode === GameMode.GHOST) {
    return false
  }

  // If the king is in check, it's not stalemate
  if (isKingInCheck(board, color)) {
    return false
  }

  // If the player has no legal moves, it's stalemate
  return !hasLegalMoves(board, color, gameMode)
}

// Helper function to check if a player has any legal moves
function hasLegalMoves(board: (ChessPiece | null)[][], color: PieceColor, gameMode: GameMode = GameMode.CLASSIC): boolean {
  for (let fromRow = 0; fromRow < 8; fromRow++) {
    for (let fromCol = 0; fromCol < 8; fromCol++) {
      const piece = board[fromRow][fromCol]
      if (piece && piece.color === color) {
        for (let toRow = 0; toRow < 8; toRow++) {
          for (let toCol = 0; toCol < 8; toCol++) {
            if (isValidMove(board, { row: fromRow, col: fromCol }, { row: toRow, col: toCol }, color, gameMode)) {
              return true
            }
          }
        }
      }
    }
  }
  return false
}

// Helper function to check if the king is in check
function isKingInCheck(board: (ChessPiece | null)[][], kingColor: PieceColor): boolean {
  const kingPosition = findKingPosition(board, kingColor)
  if (!kingPosition) return false

  const opponentColor = kingColor === PieceColor.WHITE ? PieceColor.BLACK : PieceColor.WHITE

  // Check if any opponent piece can capture the king
  for (let row = 0; row < 8; row++) {
    for (let col = 0; col < 8; col++) {
      const piece = board[row][col]
      if (piece && piece.color === opponentColor) {
        // Use a simplified version of isValidMove that doesn't check for check
        // to avoid infinite recursion
        if (canPieceMove(board, { row, col }, kingPosition)) {
          return true
        }
      }
    }
  }

  return false
}

// Simplified version of isValidMove that doesn't check for check
function canPieceMove(board: (ChessPiece | null)[][], from: Position, to: Position): boolean {
  const piece = board[from.row][from.col]
  if (!piece) return false

  const targetPiece = board[to.row][to.col]
  if (targetPiece && targetPiece.color === piece.color) return false

  switch (piece.type) {
    case PieceType.PAWN:
      return isValidPawnMove(board, from, to)
    case PieceType.ROOK:
      return isValidRookMove(board, from, to)
    case PieceType.KNIGHT:
      return isValidKnightMove(from, to)
    case PieceType.BISHOP:
      return isValidBishopMove(board, from, to)
    case PieceType.QUEEN:
      return isValidQueenMove(board, from, to)
    case PieceType.KING:
      return isValidKingMove(board, from, to)
    default:
      return false
  }
}

// Check if a pawn move is valid
function isValidPawnMove(board: (ChessPiece | null)[][], from: Position, to: Position): boolean {
  const piece = board[from.row][from.col]
  if (!piece || piece.type !== PieceType.PAWN) return false

  const direction = piece.color === PieceColor.WHITE ? -1 : 1
  const startRow = piece.color === PieceColor.WHITE ? 6 : 1

  // Moving forward one square
  if (from.col === to.col && from.row + direction === to.row && !board[to.row][to.col]) {
    return true
  }

  // Moving forward two squares from starting position
  if (
    from.col === to.col &&
    from.row === startRow &&
    from.row + 2 * direction === to.row &&
    !board[from.row + direction][from.col] &&
    !board[to.row][to.col]
  ) {
    return true
  }

  // Capturing diagonally
  if ((from.col + 1 === to.col || from.col - 1 === to.col) && from.row + direction === to.row) {
    return board[to.row][to.col] !== null
  }

  return false
}

// Check if a rook move is valid
function isValidRookMove(board: (ChessPiece | null)[][], from: Position, to: Position): boolean {
  // Rooks move horizontally or vertically
  if (from.row !== to.row && from.col !== to.col) {
    return false
  }

  // Check if the path is clear
  if (from.row === to.row) {
    // Horizontal movement
    const start = Math.min(from.col, to.col)
    const end = Math.max(from.col, to.col)

    for (let col = start + 1; col < end; col++) {
      if (board[from.row][col] !== null) {
        return false
      }
    }
  } else {
    // Vertical movement
    const start = Math.min(from.row, to.row)
    const end = Math.max(from.row, to.row)

    for (let row = start + 1; row < end; row++) {
      if (board[row][from.col] !== null) {
        return false
      }
    }
  }

  return true
}

// Check if a knight move is valid
function isValidKnightMove(from: Position, to: Position): boolean {
  const rowDiff = Math.abs(from.row - to.row)
  const colDiff = Math.abs(from.col - to.col)

  // Knights move in an L-shape: 2 squares in one direction and 1 square perpendicular
  return (rowDiff === 2 && colDiff === 1) || (rowDiff === 1 && colDiff === 2)
}

// Check if a bishop move is valid
function isValidBishopMove(board: (ChessPiece | null)[][], from: Position, to: Position): boolean {
  const rowDiff = Math.abs(from.row - to.row)
  const colDiff = Math.abs(from.col - to.col)

  // Bishops move diagonally
  if (rowDiff !== colDiff) {
    return false
  }

  // Check if the path is clear
  const rowDirection = from.row < to.row ? 1 : -1
  const colDirection = from.col < to.col ? 1 : -1

  for (let i = 1; i < rowDiff; i++) {
    if (board[from.row + i * rowDirection][from.col + i * colDirection] !== null) {
      return false
    }
  }

  return true
}

// Check if a queen move is valid
function isValidQueenMove(board: (ChessPiece | null)[][], from: Position, to: Position): boolean {
  // Queens can move like rooks or bishops
  return isValidRookMove(board, from, to) || isValidBishopMove(board, from, to)
}

// Check if a king move is valid
function isValidKingMove(board: (ChessPiece | null)[][], from: Position, to: Position): boolean {
  const rowDiff = Math.abs(from.row - to.row)
  const colDiff = Math.abs(from.col - to.col)

  // Kings move one square in any direction
  if (rowDiff <= 1 && colDiff <= 1) {
    return true
  }

  // Check for castling
  const piece = board[from.row][from.col]
  if (piece && piece.type === PieceType.KING && !piece.hasMoved && rowDiff === 0 && colDiff === 2) {
    // Determine if it's kingside or queenside castling
    const isKingSide = to.col > from.col
    const rookCol = isKingSide ? 7 : 0

    // Check if the rook is in place and hasn't moved
    const rook = board[from.row][rookCol]
    if (!rook || rook.type !== PieceType.ROOK || rook.color !== piece.color || rook.hasMoved) {
      return false
    }

    // Check if the path is clear
    const start = isKingSide ? from.col + 1 : rookCol + 1
    const end = isKingSide ? rookCol : from.col

    for (let col = start; col < end; col++) {
      if (board[from.row][col] !== null) {
        return false
      }
    }

    // Check if the king is in check or would pass through check
    const tempBoard = cloneBoard(board)
    tempBoard[from.row][from.col] = null

    // Check if the king is in check
    if (isKingInCheck(tempBoard, piece.color)) {
      return false
    }

    // Check if the king would pass through check
    tempBoard[from.row][isKingSide ? from.col + 1 : from.col - 1] = piece
    if (isKingInCheck(tempBoard, piece.color)) {
      return false
    }

    return true
  }

  return false
}

// Get all possible capture moves for a player (for ghost chess)
export function getCaptureMoves(board: (ChessPiece | null)[][], color: PieceColor): { from: Position; to: Position }[] {
  const captureMoves: { from: Position; to: Position }[] = []
  
  for (let fromRow = 0; fromRow < 8; fromRow++) {
    for (let fromCol = 0; fromCol < 8; fromCol++) {
      const piece = board[fromRow][fromCol]
      if (piece && piece.color === color) {
        for (let toRow = 0; toRow < 8; toRow++) {
          for (let toCol = 0; toCol < 8; toCol++) {
            const targetPiece = board[toRow][toCol]
            if (targetPiece && targetPiece.color !== color) {
              // Check if this piece can capture the target
              if (canPieceMove(board, { row: fromRow, col: fromCol }, { row: toRow, col: toCol })) {
                captureMoves.push({
                  from: { row: fromRow, col: fromCol },
                  to: { row: toRow, col: toCol }
                })
              }
            }
          }
        }
      }
    }
  }
  
  return captureMoves
}

// Check if a player has lost all their pieces (ghost chess win condition)
export function hasLostAllPieces(board: (ChessPiece | null)[][], color: PieceColor): boolean {
  for (let row = 0; row < 8; row++) {
    for (let col = 0; col < 8; col++) {
      const piece = board[row][col]
      if (piece && piece.color === color) {
        return false
      }
    }
  }
  return true
}
