import chess

from chess_detect import ChessDetector
from chess_detect.context import MoveContext
from chess_detect.detectors.tactics.exploiting_pin import ExploitingPinDetector


class TestExploitingPinDetector:
    """Тесты для детектора использования связки."""

    def test_attack_on_pinned_piece(self):
        """Тип A: пешка d3 нападает на связанного коня e4."""
        # Re1 связывает Ne4 на Ke8 по вертикали e
        # d3 нападает на коня — конь не может уйти (связан)
        board = chess.Board("4k3/8/8/5p2/4n3/8/3P4/4R1K1 w - - 0 1")
        move = chess.Move.from_uci("d2d3")  # d3

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

        assert detector.detect(ctx) is True

    def test_capture_through_pinned_defender(self):
        """Тип B: Rxh6 берёт коня, g7 связана и не может взять обратно."""
        # Bc3 связывает g7 на Kh8 по диагонали
        # Rxh6 берёт коня — g7 "защищает" h6, но не может ходить
        board = chess.Board("5r1k/5ppp/7n/8/8/2B2P2/2P3P1/2K4R w - - 0 1")
        move = chess.Move.from_uci("h1h6")  # Rxh6

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

        assert detector.detect(ctx) is True

    def test_no_exploit_if_pin_just_created(self):
        """Не эксплуатация, если связку только что создали (это PinDetector)."""
        # Слон b3 идёт на c4, СОЗДАВАЯ связку коня e6 на короля g8
        # Это новая связка — должен сработать PinDetector, а не этот
        board = chess.Board("6k1/8/4n3/8/8/1B6/8/4K3 w - - 0 1")
        move = chess.Move.from_uci("b3c4")  # Bc4 создаёт связку

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

        assert detector.detect(ctx) is False

    def test_no_exploit_if_attacker_not_cheaper(self):
        """Не эксплуатация: атакующий не дешевле связанной фигуры."""
        # Ладья Re1 связывает Ne4. Ферзь нападает на коня — но ферзь (9) > конь (3)
        board = chess.Board("4k3/8/8/8/4n3/8/8/Q3R1K1 w - - 0 1")
        move = chess.Move.from_uci("a1d4")  # Qd4 нападает на Ne4

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

        # Ферзь (9) >= Конь (3) — не проходит фильтр
        assert detector.detect(ctx) is False

    def test_attack_on_relative_pinned_bb5(self):
        """Тип 4: Bb5 навалился на Nd7, связанного по d-вертикали (Qd3→Nd7→Qd8)."""
        board = chess.Board(
            "r1bqnrk1/p2n1pbp/1p2p1p1/2p1P3/2B2P2/2NQB2P/PPP1N1P1/3R1RK1 w - - 0 1"
        )
        move = chess.Move.from_uci("c4b5")  # Bb5

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

        assert detector.detect(ctx) is True

    def test_no_relative_pin_if_behind_cheaper(self):
        """Не сработает: за целью стоит фигура дешевле (не относительная связка)."""
        # Bb5 атакует Nd7, за ним Ne8 (равноценный) — не относительная связка
        # И нет Qd3 давящего по вертикали
        board = chess.Board(
            "4nrk1/3n1pbp/1p2p1p1/2p1P3/2B2P2/4B2P/PPP1N1P1/3R1RK1 w - - 0 1"
        )
        move = chess.Move.from_uci("c4b5")  # Bb5

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

        assert detector.detect(ctx) is False

    def test_no_exploit_if_defender_not_pinned(self):
        """Не эксплуатация: защитник не связан."""
        # Обычное взятие — защитник может отбить
        board = chess.Board("5r1k/5ppp/7n/8/8/5P2/2P3P1/2K4R w - - 0 1")
        move = chess.Move.from_uci("h1h6")  # Rxh6

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

        # g7 НЕ связана (нет слона на диагонали) — может взять обратно
        assert detector.detect(ctx) is False

    def test_exploit_capture_through_pinned_pawn(self):
        """Взятие пешки — связанная пешка g7 не может отбить gxh6."""
        # Bc3 pins g7 to Kh8. Rxh6 takes pawn, gxh6 illegal.
        board = chess.Board("5r1k/5ppp/7p/8/8/2B2P2/2P3P1/2K4R w - - 0 1")
        move = chess.Move.from_uci("h1h6")  # Rxh6 takes pawn

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

        assert detector.detect(ctx) is True


class TestExploitingPinIntegration:
    """Интеграционные тесты использования связки."""

    def test_analyze_detects_exploiting_pin_ru(self):
        """Детектор находит использование связки на русском."""
        detector = ChessDetector(lang="ru")

        pgn = """[FEN "4k3/8/8/5p2/4n3/8/3P4/4R1K1 w - - 0 1"]

1. d3"""

        result = detector.analyze(pgn)
        assert "Использование связки" in result

    def test_analyze_detects_exploiting_pin_en(self):
        """Детектор находит использование связки на английском."""
        detector = ChessDetector(lang="en")

        pgn = """[FEN "4k3/8/8/5p2/4n3/8/3P4/4R1K1 w - - 0 1"]

1. d3"""

        result = detector.analyze(pgn)
        assert "Exploiting Pin" in result
