import chess

from ..base import BaseDetector
from ...context import MoveContext
from ...i18n import format_piece_square
from ...utils import get_piece_value, is_piece_vulnerable


class TrappedPieceDetector(BaseDetector):
    """
    Детектор пойманной фигуры (ловушка).

    Фигура считается пойманной, если:
    - Не король и не пешка
    - Сейчас под угрозой (висит или может быть взята дешевле)
    - ВСЕ ходы ведут в плохие позиции (нет спасения)
    """

    key = "trapped_piece"

    def __init__(self):
        self._trapped_sq: int | None = None

    def detect(self, ctx: MoveContext) -> bool:
        """
        Проверяет, поймал ли наш ход фигуру противника.
        """
        self._trapped_sq = None

        # При шахе нет смысла проверять — противник обязан ответить на шах
        if ctx.is_check:
            return False

        # Проверяем фигуры противника (только занятые клетки)
        for sq, piece in ctx.board_after.piece_map().items():
            if piece.color != ctx.opponent_side:
                continue

            if self._is_trapped(ctx.board_after, sq, piece):
                if not self._can_be_rescued(ctx.board_after, sq):
                    self._trapped_sq = sq
                    return True

        return False

    def format_details(self, ctx: MoveContext, lang: str) -> str:
        if self._trapped_sq is None:
            return ""
        piece = ctx.board_after.piece_at(self._trapped_sq)
        if not piece:
            return ""
        return format_piece_square(piece, self._trapped_sq, lang)

    def get_arrows(self, ctx: MoveContext) -> list[tuple[int, int]]:
        if self._trapped_sq is None:
            return []
        return [(self._trapped_sq, self._trapped_sq)]

    def _is_trapped(self, board: chess.Board, square: int, piece: chess.Piece) -> bool:
        """Проверяет, поймана ли фигура."""
        # Короли и пешки не могут быть "пойманы" в этом смысле
        if piece.piece_type in {chess.PAWN, chess.KING}:
            return False

        # Фигура должна быть в плохой позиции
        if not is_piece_vulnerable(board, square):
            return False

        # Проверяем все легальные ходы этой фигуры
        piece_value = get_piece_value(piece.piece_type)

        for move in board.generate_legal_moves(from_mask=chess.BB_SQUARES[square]):

            # Проверяем взятие — если берём фигуру >= нашей ценности, это не ловушка
            target = board.piece_at(move.to_square)
            if target and get_piece_value(target.piece_type) >= piece_value:
                return False  # Есть выгодный размен

            # Симулируем ход
            board.push(move)
            escaped = not is_piece_vulnerable(board, move.to_square)
            board.pop()

            if escaped:
                return False  # Нашли безопасное поле

        return True  # Все ходы ведут в плохие позиции

    def _can_be_rescued(self, board: chess.Board, square: int) -> bool:
        """Можно ли защитить пойманную фигуру следующим ходом?"""
        for move in board.legal_moves:
            if move.from_square == square:
                continue  # Ходы самой фигуры уже проверены в _is_trapped
            board.push(move)
            piece = board.piece_at(square)
            safe = piece is not None and not is_piece_vulnerable(board, square)
            board.pop()
            if safe:
                return True
        return False
