import chess

from chess_detect import ChessDetector
from chess_detect.context import MoveContext
from chess_detect.detectors.tactics.skewer import SkewerDetector


class TestSkewerDetector:
    """Тесты для детектора копья."""

    def test_royal_skewer_king_to_queen(self):
        """Копьё на короля: король вынужден уйти, теряет ферзя."""
        # Ладья атакует короля e5, за ним ферзь e8
        # Белый король на g1 (не мешает)
        board = chess.Board("4q3/8/8/4k3/8/8/8/R5K1 w - - 0 1")
        move = chess.Move.from_uci("a1e1")  # Re1+ шах королю e5

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

        assert detector.detect(ctx) is True

    def test_skewer_queen_to_rook(self):
        """Копьё: ферзь дороже ладьи, ферзь уходит."""
        # Слон атакует ферзя c3, за ним ладья g7 на диагонали a1-h8
        # Ладья a2 защищает слона на a1 (иначе слон висит)
        board = chess.Board("7k/6r1/8/8/8/2q5/RB6/4K3 w - - 0 1")
        move = chess.Move.from_uci("b2a1")  # Ba1 атакует c3 (ферзь) и g7 (ладья)

        # После Ba1 слон атакует: b2, c3, d4, e5, f6, g7
        # c3 — ферзь, g7 — ладья
        # Ферзь (9) > ладья (5) — копьё!

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

        assert detector.detect(ctx) is True

    def test_not_skewer_if_less_valuable_first(self):
        """Не копьё: первая фигура дешевле второй (это связка)."""
        # Слон атакует ладью c3, за ней ферзь g7 — это связка, не копьё
        board = chess.Board("7k/6q1/8/8/8/2r5/1B6/4K3 w - - 0 1")
        move = chess.Move.from_uci("b2a1")  # Ba1 атакует c3 (ладья) и g7 (ферзь)
        # Ладья (5) < ферзь (9) — это связка

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

        assert detector.detect(ctx) is False

    def test_royal_skewer_fails_if_piece_vulnerable(self):
        """Королевское копьё не работает если фигуру заберут."""
        # Rxc7+ — ладья берёт ладью с шахом, но король просто берёт Kxc7
        board = chess.Board("8/2rk2p1/3p1p2/4p3/2R1P2P/3P1KP1/8/8 w - - 0 43")
        move = chess.Move.from_uci("c4c7")  # Rxc7+

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

        # Ладья на c7 не защищена — король заберёт, копьё не работает
        assert detector.detect(ctx) is False

    def test_no_skewer_back_piece_defended(self):
        """Не копьё: заднюю фигуру нельзя взять выгодно."""
        # Qf3 атакует коня e4 (незащищён), за ним пешка b7 (защищена Сc8)
        # Ферзь (9) > пешка (1) и пешка защищена — невыгодно
        board = chess.Board("rnb1kb1r/ppp1q1pp/3p2p1/4p2Q/2B1n3/8/PPPP1P1P/RNB1K1NR w KQkq - 0 7")
        move = chess.Move.from_uci("h5f3")  # Qf3

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

        assert detector.detect(ctx) is False

    def test_no_skewer_interposition_possible(self):
        """Не копьё: между фигурами можно поставить блокирующую фигуру."""
        # Bc6 атакует Фg2 (9) за ней Лh1 (5)
        # Но между c6 и g2 три пустых поля (d5, e4, f3) — Кf3 блокирует
        board = chess.Board("rn2kb1r/p1pbq1pp/1n1p2p1/4p3/PPB5/3P4/2P2PQP/RNB1K1NR b KQkq - 0 12")
        move = chess.Move.from_uci("d7c6")  # Bc6

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

        assert detector.detect(ctx) is False

    def test_skewer_fails_if_hanging_no_check(self):
        """Копьё не работает если наша фигура висит (без шаха)."""
        # Ладья d2 идёт на d3, атакуя ферзя d4 и ладью d7
        # Но конь e1 атакует d3 — наша ладья висит после хода!
        board = chess.Board("7k/3r4/8/8/3q4/8/3R4/3Kn3 w - - 0 1")
        move = chess.Move.from_uci("d2d3")  # Rd3 — ферзь d4 первый, ладья d7 вторая
        # Ферзь (9) > ладья (5) — копьё!
        # Но конь e1 атакует d3!

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

        # Ладья висит после хода (конь e1 атакует d3), копьё без шаха — не работает
        assert detector.detect(ctx) is False


    def test_skewer_equal_value_pieces(self):
        """Копьё на равноценные фигуры: обе висят, одну заберём."""
        # Ладья a1 атакует коня b1 (3, висит) и слона c1 (3, висит)
        # Конь вынужден уйти (висит) → ладья берёт слона
        board = chess.Board("rn2kb1r/2p1q1pp/1p1p2p1/4p3/1PB5/3P3N/2P1KP1P/RNB4b b kq - 1 16")
        move = chess.Move.from_uci("a8a1")  # Rxa1

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

        assert detector.detect(ctx) is True

    def test_no_skewer_equal_value_front_defended(self):
        """Не копьё: равные по ценности, но передняя защищена (не уязвима)."""
        # Ладья атакует коня (3, защищён) и слона (3, висит)
        # Конь защищён — рокируя не обязан уходить, ладья не возьмёт (5 за 3)
        board = chess.Board("4k3/8/8/8/8/8/1K6/R1N1b3 w - - 0 1")
        move = chess.Move.from_uci("a1c1")  # Нет, ладья не может перепрыгнуть коня

        # Точнее: ладья на e1 атакует коня c1 (защищён Kb2) и слон уже на e1
        # Давай проще: ладья на a4, конь b4 (защищён пешкой a3), слон c4 (висит)
        board = chess.Board("4k3/8/8/8/1nb5/P7/8/R3K3 w - - 0 1")
        move = chess.Move.from_uci("a1a4")  # Ra4 — атакует b4 (конь) и c4 (слон)?

        # Ra4 атакует по 4-й горизонтали: b4 (конь), c4 (слон)
        # Конь b4 защищён пешкой a3? Пешка a3 (белая) атакует b4. Но конь чёрный,
        # пешка белая — пешка АТАКУЕТ коня, не защищает!
        # Нужен чёрный защитник для коня

        # Конь b4 защищён чёрной пешкой a5
        board = chess.Board("4k3/8/8/p7/1nb5/8/8/R3K3 w - - 0 1")
        move = chess.Move.from_uci("a1a4")

        # Конь b4: атакован Ra4 (5), защищён пешкой a5
        # is_piece_vulnerable(b4): атакован, защищён, cheapest attacker = rook(5) > knight(3)? Нет, 5 < 3 false
        # → не уязвим → не копьё

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

        assert detector.detect(ctx) is False

    def test_royal_skewer_fails_if_back_piece_not_profitable(self):
        """Королевское копьё не работает если заднюю фигуру невыгодно брать."""
        # Qxf2+ шах королю d2, за ним пешка c2 (защищена)
        # Ферзь (9) брать пешку (1) — невыгодно если защищена
        board = chess.Board("1n2kb1r/6pp/1p1p2p1/1r2p1N1/3q4/B2P4/2PK1PbP/8 b k - 5 25")
        move = chess.Move.from_uci("d4f2")  # Qxf2+

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

        # Пешка c2 защищена королём d2 — копьё не работает
        assert detector.detect(ctx) is False


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

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

        # Ладья атакует короля e5, за ним ферзь e8
        # Белый король на g1
        pgn = """[FEN "4q3/8/8/4k3/8/8/8/R5K1 w - - 0 1"]

1. Re1+"""

        result = detector.analyze(pgn)
        assert "Копьё" in result

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

        pgn = """[FEN "4q3/8/8/4k3/8/8/8/R5K1 w - - 0 1"]

1. Re1+"""

        result = detector.analyze(pgn)
        assert "Skewer" in result
