"""Tests for the autogenerated tutorial catalogue."""

from __future__ import annotations

import re
from pathlib import Path
from typing import List

import pytest

from common.game_engine import GameEngine, GameState
from common.tutorial_registry import GLOBAL_TUTORIAL_REGISTRY
from common.tutorial_session import TutorialSession

CATALOG_PATH = Path(__file__).resolve().parents[1] / "docs" / "source" / "games_catalog.rst"


def _parse_catalog_modules() -> List[str]:
    pattern = re.compile(r"- :mod:`([^`]+)`")
    text = CATALOG_PATH.read_text(encoding="utf-8")
    return pattern.findall(text)


class DummyEngine(GameEngine[str, int]):
    """Minimal engine used to validate tutorial progression."""

    def __init__(self) -> None:
        super().__init__()
        self.state = GameState.NOT_STARTED
        self.turns = 0

    def reset(self) -> None:
        self.state = GameState.NOT_STARTED
        self.turns = 0

    def is_game_over(self) -> bool:
        return self.state is GameState.FINISHED

    def get_current_player(self) -> int:
        return 0

    def get_valid_moves(self) -> List[str]:
        if self.is_game_over():
            return []
        return ["play"]

    def make_move(self, move: str) -> bool:
        if move != "play" or self.is_game_over():
            return False
        self.turns += 1
        if self.state is GameState.NOT_STARTED:
            self.state = GameState.IN_PROGRESS
        if self.turns >= 3:
            self.state = GameState.FINISHED
        return True

    def get_winner(self) -> int | None:
        return 0 if self.is_game_over() else None

    def get_game_state(self) -> GameState:
        return self.state


def test_catalog_matches_registry() -> None:
    """Ensure the registry tracks every module listed in the documentation."""

    documented = set(_parse_catalog_modules())
    registered = set(GLOBAL_TUTORIAL_REGISTRY.available_games())
    assert documented == registered


@pytest.mark.parametrize("game_key", [GLOBAL_TUTORIAL_REGISTRY.available_games()[0]])
def test_tutorial_session_progression(game_key: str) -> None:
    """Tutorial sessions should advance steps when moves succeed."""

    registration = GLOBAL_TUTORIAL_REGISTRY.get_registration(game_key)
    tutorial = registration.tutorial_class()
    game = DummyEngine()
    session = TutorialSession(
        game,
        tutorial,
        strategy_provider=registration.strategy_provider,
        probability_calculator=registration.probability_calculator,
    )

    # Initial probability is low because the game has not started.
    probability = session.estimate_progress()
    assert probability is not None
    assert probability.endswith("%")

    # Step 1 completes after the first successful move.
    success, feedback = session.apply_move("play")
    assert success
    assert feedback.completed_step is not None

    # Step 2 requires the game to be in progress and completes on the second move.
    success, feedback = session.apply_move("play")
    assert success
    assert feedback.completed_step is not None
    assert feedback.next_step is not None

    # Step 3 completes when the game finishes.
    success, feedback = session.apply_move("play")
    assert success
    assert feedback.tutorial_completed
    assert session.get_current_step() is None


def test_strategy_tip_provider_available() -> None:
    """Every tutorial should expose at least one strategy tip."""

    for game_key in GLOBAL_TUTORIAL_REGISTRY.available_games():
        provider = GLOBAL_TUTORIAL_REGISTRY.get_strategy_provider(game_key)
        assert provider.get_random_tip() is not None
