import chess

from chess_detect import ChessDetector
from chess_detect.context import MoveContext
from chess_detect.detectors.tactics.removing_defender import (
    RemovingDefenderMaterialDetector,
    RemovingDefenderMateDetector,
)


class TestRemovingDefenderMaterialDetector:
    """Тесты для детектора уничтожения защитника (выигрыш фигуры)."""

    def test_removing_defender_exposes_piece(self):
        """Взятие защитника оставляет фигуру висящей."""
        # Конь c3 защищает слона e4
        # Ферзь берёт коня — слон теперь висит (слон b1 атакует e4)
        board = chess.Board("4k3/8/8/8/4b3/Q1n5/8/1B2K3 w - - 0 1")
        move = chess.Move.from_uci("a3c3")  # Qxc3

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMaterialDetector()

        assert detector.detect(ctx) is True

    def test_removal_enables_winning_capture(self):
        """Уничтожение защитника позволяет выгодное взятие."""
        # Конь c3 защищает ферзя e4
        # Пешка берёт коня — теперь ферзь можно взять слоном b1
        board = chess.Board("4k3/8/8/8/4q3/2n5/3P4/1B2K3 w - - 0 1")
        move = chess.Move.from_uci("d2c3")  # dxc3

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMaterialDetector()

        assert detector.detect(ctx) is True

    def test_no_removal_if_still_defended(self):
        """Не уничтожение защитника, если фигура всё ещё защищена."""
        # Два защитника у слона e4: конь c3 и конь f6
        # Берём один — слон всё ещё защищён
        board = chess.Board("4k3/8/5n2/8/4b3/Q1n5/8/1B2K3 w - - 0 1")
        move = chess.Move.from_uci("a3c3")  # Qxc3

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMaterialDetector()

        assert detector.detect(ctx) is False

    def test_no_removal_if_capturer_recaptured(self):
        """Не уничтожение защитника, если нашу фигуру отберут и угроза исчезнет."""
        # Слон g2 защищал ладью f1. Чёрный слон берёт Bxg2.
        # Но слон на g2 будет отбит (Kxg2), и угрозы f1 больше нет.
        board = chess.Board("2r4r/QpP1kpp1/3p2n1/3Pp3/4P1q1/3P1NPb/6BP/2R2RK1 b - - 0 26")
        move = chess.Move.from_uci("h3g2")  # Bxg2

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMaterialDetector()

        # Слон на g2 под боем короля — его отберут, угроза f1 исчезнет
        assert detector.detect(ctx) is False

    def test_no_removal_if_not_capture(self):
        """Без взятия — не уничтожение защитника."""
        board = chess.Board("4k3/8/8/8/4b3/Q1n5/8/1B2K3 w - - 0 1")
        move = chess.Move.from_uci("a3b4")  # Qb4 — не взятие

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMaterialDetector()

        assert detector.detect(ctx) is False


class TestRemovingDefenderMateDetector:
    """Тесты для детектора уничтожения защитника (угроза мата)."""

    def test_removing_defender_enables_mate(self):
        """Взятие защитника открывает угрозу мата."""
        # Ладья g6 блокирует слона от h7, защищая короля
        # Bxg6 — слон встаёт на g6, контролирует h7, угроза Qc8#
        board = chess.Board("7k/6p1/6r1/8/4B3/2Q5/8/4K3 w - - 0 1")
        move = chess.Move.from_uci("e4g6")  # Bxg6

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMateDetector()

        assert detector.detect(ctx) is True

    def test_no_removing_defender_mate_with_check(self):
        """Не уничтожение защитника при шахе — противник ответит и угроза исчезнет."""
        # Qxg2+ — ферзь берёт ферзя с шахом
        # Формально есть мат в 1 (Nf4#), но после Kxg2 угроза исчезает
        board = chess.Board("2r4r/1pP1kpp1/3p4/3Pp3/4P3/3P1NPq/4n1QP/2R2R1K b - - 6 30")
        move = chess.Move.from_uci("h3g2")  # Qxg2+

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMateDetector()

        assert detector.detect(ctx) is False

    def test_no_removing_defender_mate_if_already_checkmate(self):
        """Если ход уже мат — это не 'угроза мата', а просто мат."""
        # Qxf7# — ферзь берёт пешку f7 с матом
        # Не должен срабатывать removing_defender_mate
        board = chess.Board("rnbqkbnr/pppp1p1p/6p1/4p3/2B1P3/5Q2/PPPP1PPP/RNB1K1NR w KQkq - 0 3")
        move = chess.Move.from_uci("f3f7")  # Qxf7#

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMateDetector()

        assert detector.detect(ctx) is False

    def test_no_mate_threat_after_capture(self):
        """Нет угрозы мата после взятия — не детектируется."""
        # Просто взятие без угрозы мата
        board = chess.Board("4k3/8/8/8/4b3/Q1n5/8/1B2K3 w - - 0 1")
        move = chess.Move.from_uci("a3c3")  # Qxc3

        ctx = MoveContext(board, move)
        detector = RemovingDefenderMateDetector()

        # Нет угрозы мата в 1 ход
        assert detector.detect(ctx) is False


class TestRemovingDefenderIntegration:
    """Интеграционные тесты."""

    def test_analyze_detects_removing_defender_material_ru(self):
        """Детектор находит уничтожение защитника (материал) на русском."""
        detector = ChessDetector(lang="ru")

        pgn = """[FEN "4k3/8/8/8/4b3/Q1n5/8/1B2K3 w - - 0 1"]

1. Qxc3"""

        result = detector.analyze(pgn)
        assert "выигрыш фигуры" in result

    def test_analyze_detects_removing_defender_material_en(self):
        """Детектор находит уничтожение защитника (материал) на английском."""
        detector = ChessDetector(lang="en")

        pgn = """[FEN "4k3/8/8/8/4b3/Q1n5/8/1B2K3 w - - 0 1"]

1. Qxc3"""

        result = detector.analyze(pgn)
        assert "winning material" in result

    def test_analyze_detects_removing_defender_mate_ru(self):
        """Детектор находит уничтожение защитника (мат) на русском."""
        detector = ChessDetector(lang="ru")

        pgn = """[FEN "7k/6p1/6r1/8/4B3/2Q5/8/4K3 w - - 0 1"]

1. Bxg6"""

        result = detector.analyze(pgn)
        assert "угроза мата" in result

    def test_analyze_detects_removing_defender_mate_en(self):
        """Детектор находит уничтожение защитника (мат) на английском."""
        detector = ChessDetector(lang="en")

        pgn = """[FEN "7k/6p1/6r1/8/4B3/2Q5/8/4K3 w - - 0 1"]

1. Bxg6"""

        result = detector.analyze(pgn)
        assert "mate threat" in result
