import io

import chess
import chess.pgn
import chess.svg

from .context import MoveContext
from .detectors import (
    DoubleCheckDetector,
    ForkDetector,
    DiscoveredCheckDetector,
    PinDetector,
    SkewerDetector,
    TrappedPieceDetector,
    HangingCaptureDetector,
    RemovingDefenderMaterialDetector,
    RemovingDefenderMateDetector,
    ExploitingPinDetector,
)
from .detectors.base import BaseDetector
from .i18n import get_theme_name


class ChessDetector:
    """
    Главный класс для анализа шахматных партий.

    Анализирует PGN и возвращает PGN с разметкой тактических тем в комментариях.
    """

    def __init__(self, lang: str = "ru"):
        """
        Args:
            lang: Язык разметки ("ru" или "en").
        """
        self.lang = lang

        # Список всех детекторов
        self.detectors: list[BaseDetector] = [
            DoubleCheckDetector(),
            ForkDetector(),
            DiscoveredCheckDetector(),
            PinDetector(),
            SkewerDetector(),
            TrappedPieceDetector(),
            HangingCaptureDetector(),
            RemovingDefenderMaterialDetector(),
            RemovingDefenderMateDetector(),
            ExploitingPinDetector(),
        ]

    def analyze(self, pgn: str) -> str:
        """
        Анализирует PGN и возвращает PGN с разметкой тем.

        Args:
            pgn: Строка с PGN (может содержать несколько партий).

        Returns:
            PGN с комментариями-темами после ходов.
        """
        pgn_io = io.StringIO(pgn)
        results = []

        # Читаем все партии из PGN
        while True:
            game = chess.pgn.read_game(pgn_io)
            if game is None:
                break

            # Анализируем партию
            self._analyze_game(game)

            # Экспортируем с разметкой
            exporter = chess.pgn.StringExporter(headers=True, variations=True, comments=True)
            results.append(game.accept(exporter))

        if not results:
            return pgn

        return "\n\n".join(results)

    def _analyze_game(self, game: chess.pgn.Game) -> None:
        """Анализирует одну партию и добавляет комментарии."""
        board = game.board()
        node = game

        for move in game.mainline_moves():
            # Создаём контекст для детекторов
            ctx = MoveContext(board, move)

            # При мате тактические темы бессмысленны — партия окончена
            if ctx.board_after.is_checkmate():
                board.push(move)
                node = node.next()
                continue

            # Собираем найденные темы
            themes = []
            all_arrows = []
            for detector in self.detectors:
                if detector.detect(ctx):
                    theme_name = get_theme_name(detector.key, self.lang)
                    details = detector.format_details(ctx, self.lang)
                    if details:
                        theme_name = f"{theme_name} ({details})"
                    themes.append(theme_name)
                    all_arrows.extend(detector.get_arrows(ctx))

            # Делаем ход
            board.push(move)
            node = node.next()

            # Добавляем комментарий с темами и стрелки
            if themes and node is not None:
                existing_comment = node.comment
                themes_str = ", ".join(themes)

                if existing_comment:
                    node.comment = f"{existing_comment}, {themes_str}"
                else:
                    node.comment = themes_str

                if all_arrows:
                    seen = set()
                    arrows = []
                    for t, h in all_arrows:
                        if (t, h) not in seen:
                            seen.add((t, h))
                            arrows.append(chess.svg.Arrow(t, h, color="green"))
                    node.set_arrows(arrows)
