import chess

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


class DiscoveredCheckDetector(BaseDetector):
    """
    Детектор вскрытого шаха.

    Вскрытый шах — фигура уходит и открывает линию атаки другой фигуры на короля.

    Полезен только если отходящая фигура делает что-то выгодное:
    1. Съедает фигуру (любую)
    2. Нападает на более ценную фигуру
    3. Нападает на незащищённую фигуру
    """

    key = "discovered_check"

    def __init__(self):
        self._checker_sq: int | None = None
        self._target_sq: int | None = None

    def detect(self, ctx: MoveContext) -> bool:
        self._checker_sq = None
        self._target_sq = None

        # Должен быть шах
        if not ctx.is_check:
            return False

        # Шах должен быть вскрытым — от фигуры которая НЕ ходила
        checker_sq = None
        for sq in ctx.board_after.checkers():
            if sq != ctx.move.to_square:
                checker_sq = sq
                break
        if checker_sq is None:
            return False

        self._checker_sq = checker_sq

        # Отходящая фигура должна делать что-то полезное

        piece = ctx.moved_piece
        if piece is None:
            return False

        piece_value = get_piece_value(piece.piece_type)

        # Ищем лучшую угрозу от переместившейся фигуры
        best_target = None
        for target_sq in ctx.piece_attacks:
            target = ctx.board_after.piece_at(target_sq)

            if target is None:
                continue

            if target.color == ctx.moving_side:
                continue

            # Атака на короля — это сам шах, не дополнительная выгода
            if target.piece_type == chess.KING:
                continue

            target_value = get_piece_value(target.piece_type)

            # Более ценная фигура — выгодный размен
            if target_value > piece_value:
                best_target = target_sq
                break

            # Незащищённая фигура — заберём бесплатно
            if not ctx.board_after.is_attacked_by(ctx.opponent_side, target_sq):
                if best_target is None:
                    best_target = target_sq

        if best_target is not None:
            self._target_sq = best_target
            return True

        # Взятие без дополнительной угрозы — тоже выгодно
        # (противник не может отбить из-за шаха)
        if ctx.is_capture:
            # Ищем любую угрозу (при шахе даже защищённая фигура под ударом)
            for target_sq in ctx.piece_attacks:
                target = ctx.board_after.piece_at(target_sq)
                if target and target.color != ctx.moving_side and target.piece_type != chess.KING:
                    self._target_sq = target_sq
                    return True
            self._target_sq = ctx.move.to_square
            return True

        return False

    def format_details(self, ctx: MoveContext, lang: str) -> str:
        if self._checker_sq is None:
            return ""
        checker = ctx.board_after.piece_at(self._checker_sq)
        if not checker:
            return ""
        ch = format_piece_square(checker, self._checker_sq, lang)
        if self._target_sq is not None:
            target = ctx.board_after.piece_at(self._target_sq)
            if target:
                # При взятии — показываем взятую фигуру (из board_before)
                if self._target_sq == ctx.move.to_square and ctx.captured_piece:
                    t = format_piece_square(ctx.captured_piece, self._target_sq, lang)
                else:
                    t = format_piece_square(target, self._target_sq, lang)
                moved = ctx.moved_piece
                if moved:
                    m = format_piece_square(moved, ctx.move.to_square, lang)
                    return f"{ch}+, {m} \u2192 {t}"
        return ch

    def get_arrows(self, ctx: MoveContext) -> list[tuple[int, int]]:
        result = []
        king_sq = ctx.board_after.king(ctx.opponent_side)
        if self._checker_sq is not None and king_sq is not None:
            result.append((self._checker_sq, king_sq))
        if self._target_sq is not None:
            result.append((ctx.move.to_square, self._target_sq))
            result.append((self._target_sq, self._target_sq))
        return result
