"""Pytest fixtures for the core game engine tests.

This module provides reusable fixtures for testing the game engine:
- Sample card definitions (Pokemon, Trainer, Energy)
- Pre-configured game states
- Seeded RNG instances for deterministic testing
- Helper functions for creating test data

Usage:
    def test_something(sample_pokemon, seeded_rng):
        # sample_pokemon is a CardDefinition
        # seeded_rng is a SeededRandom instance
        pass
"""

import pytest

from app.core.config import RulesConfig
from app.core.enums import (
    CardType,
    EnergyType,
    ModifierMode,
    PokemonStage,
    PokemonVariant,
    TrainerType,
    TurnPhase,
)
from app.core.models.card import (
    Ability,
    Attack,
    CardDefinition,
    CardInstance,
    WeaknessResistance,
)
from app.core.models.game_state import GameState, PlayerState
from app.core.rng import SeededRandom

# ============================================================================
# RNG Fixtures
# ============================================================================


@pytest.fixture
def seeded_rng() -> SeededRandom:
    """Provide a SeededRandom instance with a fixed seed for deterministic tests.

    The seed 42 is used consistently across tests for reproducibility.
    """
    return SeededRandom(seed=42)


@pytest.fixture
def rng_factory():
    """Factory fixture to create SeededRandom instances with custom seeds.

    Usage:
        def test_something(rng_factory):
            rng1 = rng_factory(seed=100)
            rng2 = rng_factory(seed=200)
    """

    def _create_rng(seed: int = 42) -> SeededRandom:
        return SeededRandom(seed=seed)

    return _create_rng


# ============================================================================
# Card Definition Fixtures - Pokemon
# ============================================================================


@pytest.fixture
def pikachu_def() -> CardDefinition:
    """Basic Lightning Pokemon - Pikachu.

    A simple Basic Pokemon with one attack and standard stats.
    Used as the canonical "basic Pokemon" in tests.
    """
    return CardDefinition(
        id="pikachu_base_001",
        name="Pikachu",
        card_type=CardType.POKEMON,
        stage=PokemonStage.BASIC,
        variant=PokemonVariant.NORMAL,
        hp=60,
        pokemon_type=EnergyType.LIGHTNING,
        attacks=[
            Attack(
                name="Thunder Shock",
                cost=[EnergyType.LIGHTNING],
                damage=20,
                effect_id="may_paralyze",
                effect_params={"chance": 0.5},
                effect_description="Flip a coin. If heads, the Defending Pokemon is now Paralyzed.",
            ),
        ],
        weakness=WeaknessResistance(
            energy_type=EnergyType.FIGHTING, mode=ModifierMode.MULTIPLICATIVE, value=2
        ),
        retreat_cost=1,
        rarity="common",
        set_id="base",
    )


@pytest.fixture
def raichu_def() -> CardDefinition:
    """Stage 1 Lightning Pokemon - Raichu.

    Evolves from Pikachu. Used for evolution tests.
    """
    return CardDefinition(
        id="raichu_base_001",
        name="Raichu",
        card_type=CardType.POKEMON,
        stage=PokemonStage.STAGE_1,
        variant=PokemonVariant.NORMAL,
        evolves_from="Pikachu",
        hp=90,
        pokemon_type=EnergyType.LIGHTNING,
        attacks=[
            Attack(
                name="Thunder",
                cost=[EnergyType.LIGHTNING, EnergyType.LIGHTNING, EnergyType.COLORLESS],
                damage=60,
            ),
        ],
        weakness=WeaknessResistance(
            energy_type=EnergyType.FIGHTING, mode=ModifierMode.MULTIPLICATIVE, value=2
        ),
        retreat_cost=1,
        rarity="rare",
        set_id="base",
    )


@pytest.fixture
def charizard_def() -> CardDefinition:
    """Stage 2 Fire Pokemon - Charizard.

    Classic high-HP Stage 2 Pokemon. Evolves from Charmeleon.
    """
    return CardDefinition(
        id="charizard_base_001",
        name="Charizard",
        card_type=CardType.POKEMON,
        stage=PokemonStage.STAGE_2,
        variant=PokemonVariant.NORMAL,
        evolves_from="Charmeleon",
        hp=120,
        pokemon_type=EnergyType.FIRE,
        attacks=[
            Attack(
                name="Fire Spin",
                cost=[EnergyType.FIRE, EnergyType.FIRE, EnergyType.FIRE, EnergyType.FIRE],
                damage=100,
                effect_id="discard_energy",
                effect_params={"count": 2, "type": "fire"},
            ),
        ],
        weakness=WeaknessResistance(
            energy_type=EnergyType.WATER, mode=ModifierMode.MULTIPLICATIVE, value=2
        ),
        resistance=WeaknessResistance(
            energy_type=EnergyType.FIGHTING, mode=ModifierMode.ADDITIVE, value=-30
        ),
        retreat_cost=3,
        rarity="rare_holo",
        set_id="base",
    )


@pytest.fixture
def mewtwo_ex_def() -> CardDefinition:
    """Basic EX Pokemon - Mewtwo EX.

    High-HP Pokemon worth 2 knockout points.
    """
    return CardDefinition(
        id="mewtwo_ex_001",
        name="Mewtwo EX",
        card_type=CardType.POKEMON,
        stage=PokemonStage.BASIC,
        variant=PokemonVariant.EX,
        hp=170,
        pokemon_type=EnergyType.PSYCHIC,
        attacks=[
            Attack(
                name="Psydrive",
                cost=[EnergyType.PSYCHIC, EnergyType.COLORLESS],
                damage=120,
                effect_id="discard_energy",
                effect_params={"count": 1, "type": "any"},
            ),
        ],
        weakness=WeaknessResistance(
            energy_type=EnergyType.PSYCHIC, mode=ModifierMode.MULTIPLICATIVE, value=2
        ),
        retreat_cost=2,
        rarity="ultra_rare",
        set_id="ex_series",
    )


@pytest.fixture
def pikachu_v_def() -> CardDefinition:
    """Basic V Pokemon - Pikachu V.

    V Pokemon worth 2 knockout points.
    """
    return CardDefinition(
        id="pikachu_v_001",
        name="Pikachu V",
        card_type=CardType.POKEMON,
        stage=PokemonStage.BASIC,
        variant=PokemonVariant.V,
        hp=190,
        pokemon_type=EnergyType.LIGHTNING,
        attacks=[
            Attack(
                name="Volt Tackle",
                cost=[EnergyType.LIGHTNING, EnergyType.LIGHTNING, EnergyType.COLORLESS],
                damage=210,
                effect_id="self_damage",
                effect_params={"amount": 30},
            ),
        ],
        weakness=WeaknessResistance(
            energy_type=EnergyType.FIGHTING, mode=ModifierMode.MULTIPLICATIVE, value=2
        ),
        retreat_cost=2,
        rarity="ultra_rare",
        set_id="v_series",
    )


@pytest.fixture
def pikachu_vmax_def() -> CardDefinition:
    """VMAX Pokemon - Pikachu VMAX.

    Evolves from Pikachu V, worth 3 knockout points.
    """
    return CardDefinition(
        id="pikachu_vmax_001",
        name="Pikachu VMAX",
        card_type=CardType.POKEMON,
        stage=PokemonStage.BASIC,  # Stage is still Basic
        variant=PokemonVariant.VMAX,  # Variant indicates V evolution
        evolves_from="Pikachu V",
        hp=310,
        pokemon_type=EnergyType.LIGHTNING,
        attacks=[
            Attack(
                name="G-Max Volt Crash",
                cost=[EnergyType.LIGHTNING, EnergyType.LIGHTNING, EnergyType.LIGHTNING],
                damage=270,
            ),
        ],
        weakness=WeaknessResistance(
            energy_type=EnergyType.FIGHTING, mode=ModifierMode.MULTIPLICATIVE, value=2
        ),
        retreat_cost=3,
        rarity="secret_rare",
        set_id="vmax_series",
    )


@pytest.fixture
def pokemon_with_ability_def() -> CardDefinition:
    """Pokemon with an Ability - Shaymin EX.

    Used for ability testing.
    """
    return CardDefinition(
        id="shaymin_ex_001",
        name="Shaymin EX",
        card_type=CardType.POKEMON,
        stage=PokemonStage.BASIC,
        variant=PokemonVariant.EX,
        hp=110,
        pokemon_type=EnergyType.COLORLESS,
        abilities=[
            Ability(
                name="Set Up",
                effect_id="draw_until_hand_size",
                effect_params={"count": 6},
                effect_description="When you play this Pokemon from your hand to your Bench, "
                "you may draw cards until you have 6 cards in your hand.",
                once_per_turn=True,
            ),
        ],
        attacks=[
            Attack(
                name="Sky Return",
                cost=[EnergyType.COLORLESS, EnergyType.COLORLESS],
                damage=30,
                effect_id="return_to_hand",
            ),
        ],
        retreat_cost=1,
        rarity="ultra_rare",
        set_id="ex_series",
    )


# ============================================================================
# Card Definition Fixtures - Trainers
# ============================================================================


@pytest.fixture
def potion_def() -> CardDefinition:
    """Item card - Potion.

    Basic healing item.
    """
    return CardDefinition(
        id="potion_base_001",
        name="Potion",
        card_type=CardType.TRAINER,
        trainer_type=TrainerType.ITEM,
        effect_id="heal",
        effect_params={"amount": 30},
        effect_description="Heal 30 damage from one of your Pokemon.",
        rarity="common",
        set_id="base",
    )


@pytest.fixture
def professor_oak_def() -> CardDefinition:
    """Supporter card - Professor Oak.

    Classic draw supporter.
    """
    return CardDefinition(
        id="professor_oak_001",
        name="Professor Oak",
        card_type=CardType.TRAINER,
        trainer_type=TrainerType.SUPPORTER,
        effect_id="discard_hand_draw",
        effect_params={"draw_count": 7},
        effect_description="Discard your hand and draw 7 cards.",
        rarity="uncommon",
        set_id="base",
    )


@pytest.fixture
def pokemon_center_def() -> CardDefinition:
    """Stadium card - Pokemon Center.

    Example stadium that stays in play.
    """
    return CardDefinition(
        id="pokemon_center_001",
        name="Pokemon Center",
        card_type=CardType.TRAINER,
        trainer_type=TrainerType.STADIUM,
        effect_id="stadium_heal_between_turns",
        effect_params={"amount": 20},
        effect_description="Between turns, heal 20 damage from each player's Active Pokemon.",
        rarity="uncommon",
        set_id="base",
    )


@pytest.fixture
def choice_band_def() -> CardDefinition:
    """Tool card - Choice Band.

    Damage-boosting tool.
    """
    return CardDefinition(
        id="choice_band_001",
        name="Choice Band",
        card_type=CardType.TRAINER,
        trainer_type=TrainerType.TOOL,
        effect_id="damage_boost_vs_ex_gx",
        effect_params={"amount": 30},
        effect_description="The attacks of the Pokemon this is attached to do 30 more damage "
        "to your opponent's Active Pokemon-EX or Pokemon-GX.",
        rarity="uncommon",
        set_id="modern",
    )


# ============================================================================
# Card Definition Fixtures - Energy
# ============================================================================


@pytest.fixture
def lightning_energy_def() -> CardDefinition:
    """Basic Lightning Energy."""
    return CardDefinition(
        id="lightning_energy_001",
        name="Lightning Energy",
        card_type=CardType.ENERGY,
        energy_type=EnergyType.LIGHTNING,
        energy_provides=[EnergyType.LIGHTNING],
        rarity="common",
        set_id="base",
    )


@pytest.fixture
def fire_energy_def() -> CardDefinition:
    """Basic Fire Energy."""
    return CardDefinition(
        id="fire_energy_001",
        name="Fire Energy",
        card_type=CardType.ENERGY,
        energy_type=EnergyType.FIRE,
        energy_provides=[EnergyType.FIRE],
        rarity="common",
        set_id="base",
    )


@pytest.fixture
def double_colorless_energy_def() -> CardDefinition:
    """Special Energy - Double Colorless Energy.

    Provides 2 Colorless energy.
    """
    return CardDefinition(
        id="dce_001",
        name="Double Colorless Energy",
        card_type=CardType.ENERGY,
        energy_type=EnergyType.COLORLESS,
        energy_provides=[EnergyType.COLORLESS, EnergyType.COLORLESS],
        rarity="uncommon",
        set_id="base",
    )


# ============================================================================
# Card Registry Fixtures
# ============================================================================


@pytest.fixture
def basic_card_registry(
    pikachu_def,
    raichu_def,
    charizard_def,
    potion_def,
    professor_oak_def,
    lightning_energy_def,
    fire_energy_def,
) -> dict[str, CardDefinition]:
    """A basic card registry with common test cards.

    Includes: Pikachu, Raichu, Charizard, Potion, Professor Oak, basic energy.
    """
    cards = [
        pikachu_def,
        raichu_def,
        charizard_def,
        potion_def,
        professor_oak_def,
        lightning_energy_def,
        fire_energy_def,
    ]
    return {card.id: card for card in cards}


# ============================================================================
# Card Instance Factory
# ============================================================================


@pytest.fixture
def card_instance_factory():
    """Factory fixture to create CardInstance objects.

    Usage:
        def test_something(card_instance_factory):
            card = card_instance_factory("pikachu_base_001")
            card_with_damage = card_instance_factory("pikachu_base_001", damage=30)
            card_evolved = card_instance_factory("raichu_base_001", turn_evolved=2)
    """
    _counter = [0]

    def _create_instance(
        definition_id: str,
        instance_id: str | None = None,
        damage: int = 0,
        turn_played: int | None = None,
        turn_evolved: int | None = None,
    ) -> CardInstance:
        if instance_id is None:
            _counter[0] += 1
            instance_id = f"inst_{definition_id}_{_counter[0]}"

        card = CardInstance(
            instance_id=instance_id,
            definition_id=definition_id,
            damage=damage,
            turn_played=turn_played,
        )
        if turn_evolved is not None:
            card.turn_evolved = turn_evolved
        return card

    return _create_instance


# ============================================================================
# Game State Fixtures
# ============================================================================


@pytest.fixture
def empty_game_state(basic_card_registry) -> GameState:
    """An empty game state ready for setup.

    Has two players with empty zones, in SETUP phase.
    """
    return GameState(
        game_id="test_game_001",
        rules=RulesConfig(),
        card_registry=basic_card_registry,
        players={
            "player1": PlayerState(player_id="player1"),
            "player2": PlayerState(player_id="player2"),
        },
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=0,
        phase=TurnPhase.SETUP,
    )


@pytest.fixture
def mid_game_state(basic_card_registry, card_instance_factory) -> GameState:
    """A game state in the middle of play.

    - Turn 3, player1's turn, MAIN phase
    - Player1: Pikachu active, Raichu on bench, 3 cards in hand, score 1
    - Player2: Charizard active, 4 cards in hand, score 0
    - Both players have cards in deck and discard
    """
    player1 = PlayerState(player_id="player1")
    player2 = PlayerState(player_id="player2")

    # Player 1 setup
    player1.active.add(card_instance_factory("pikachu_base_001", turn_played=1))
    player1.bench.add(card_instance_factory("raichu_base_001", turn_played=2))
    for _ in range(3):
        player1.hand.add(card_instance_factory("lightning_energy_001"))
    for _ in range(10):
        player1.deck.add(card_instance_factory("pikachu_base_001"))
    player1.discard.add(card_instance_factory("potion_base_001"))
    player1.score = 1

    # Player 2 setup
    player2.active.add(card_instance_factory("charizard_base_001", turn_played=1, damage=40))
    for _ in range(4):
        player2.hand.add(card_instance_factory("fire_energy_001"))
    for _ in range(8):
        player2.deck.add(card_instance_factory("charizard_base_001"))
    player2.discard.add(card_instance_factory("professor_oak_001"))
    player2.score = 0

    return GameState(
        game_id="test_game_mid",
        rules=RulesConfig(),
        card_registry=basic_card_registry,
        players={"player1": player1, "player2": player2},
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=3,
        phase=TurnPhase.MAIN,
        first_turn_completed=True,
    )


@pytest.fixture
def game_near_win_state(basic_card_registry, card_instance_factory) -> GameState:
    """A game state where player1 is about to win (3/4 points).

    Used for testing win condition detection.
    """
    player1 = PlayerState(player_id="player1")
    player2 = PlayerState(player_id="player2")

    # Player 1 setup - one knockout away from winning
    player1.active.add(card_instance_factory("pikachu_base_001"))
    player1.score = 3  # 4 points needed to win

    # Player 2 setup - low HP Pokemon active
    damaged_pikachu = card_instance_factory("pikachu_base_001", damage=50)  # 10 HP remaining
    player2.active.add(damaged_pikachu)

    return GameState(
        game_id="test_game_near_win",
        rules=RulesConfig(),  # Default: 4 points to win
        card_registry=basic_card_registry,
        players={"player1": player1, "player2": player2},
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=5,
        phase=TurnPhase.ATTACK,
        first_turn_completed=True,
    )


# ============================================================================
# Rules Config Fixtures
# ============================================================================


@pytest.fixture
def default_rules() -> RulesConfig:
    """Default Mantimon TCG rules.

    40-card deck, 4 points to win, Pokemon Pocket-style energy.
    """
    return RulesConfig()


@pytest.fixture
def standard_tcg_rules() -> RulesConfig:
    """Standard Pokemon TCG rules.

    60-card deck, 6 prizes, no energy deck.
    """
    return RulesConfig.standard_pokemon_tcg()


# ============================================================================
# Additional Card Definition Fixtures for Evolution Testing
# ============================================================================


@pytest.fixture
def charmander_def() -> CardDefinition:
    """Basic Fire Pokemon - Charmander.

    Used for evolution chain testing (Charmander -> Charmeleon -> Charizard).
    """
    return CardDefinition(
        id="charmander_base_001",
        name="Charmander",
        card_type=CardType.POKEMON,
        stage=PokemonStage.BASIC,
        variant=PokemonVariant.NORMAL,
        hp=50,
        pokemon_type=EnergyType.FIRE,
        attacks=[
            Attack(
                name="Scratch",
                cost=[EnergyType.COLORLESS],
                damage=10,
            ),
        ],
        weakness=WeaknessResistance(
            energy_type=EnergyType.WATER, mode=ModifierMode.MULTIPLICATIVE, value=2
        ),
        retreat_cost=1,
        rarity="common",
        set_id="base",
    )


@pytest.fixture
def charmeleon_def() -> CardDefinition:
    """Stage 1 Fire Pokemon - Charmeleon.

    Evolves from Charmander. Used for evolution chain testing.
    """
    return CardDefinition(
        id="charmeleon_base_001",
        name="Charmeleon",
        card_type=CardType.POKEMON,
        stage=PokemonStage.STAGE_1,
        variant=PokemonVariant.NORMAL,
        evolves_from="Charmander",
        hp=80,
        pokemon_type=EnergyType.FIRE,
        attacks=[
            Attack(
                name="Slash",
                cost=[EnergyType.FIRE, EnergyType.COLORLESS],
                damage=30,
            ),
        ],
        weakness=WeaknessResistance(
            energy_type=EnergyType.WATER, mode=ModifierMode.MULTIPLICATIVE, value=2
        ),
        retreat_cost=1,
        rarity="uncommon",
        set_id="base",
    )


# ============================================================================
# Extended Card Registry Fixture
# ============================================================================


@pytest.fixture
def extended_card_registry(
    pikachu_def,
    raichu_def,
    charmander_def,
    charmeleon_def,
    charizard_def,
    mewtwo_ex_def,
    pikachu_v_def,
    pikachu_vmax_def,
    pokemon_with_ability_def,
    potion_def,
    professor_oak_def,
    pokemon_center_def,
    choice_band_def,
    lightning_energy_def,
    fire_energy_def,
    double_colorless_energy_def,
) -> dict[str, CardDefinition]:
    """Extended card registry with all test cards.

    Includes full evolution chains and all card types for comprehensive testing.
    """
    cards = [
        pikachu_def,
        raichu_def,
        charmander_def,
        charmeleon_def,
        charizard_def,
        mewtwo_ex_def,
        pikachu_v_def,
        pikachu_vmax_def,
        pokemon_with_ability_def,
        potion_def,
        professor_oak_def,
        pokemon_center_def,
        choice_band_def,
        lightning_energy_def,
        fire_energy_def,
        double_colorless_energy_def,
    ]
    return {card.id: card for card in cards}


# ============================================================================
# Game State Fixtures for Rules Validation
# ============================================================================


@pytest.fixture
def game_in_main_phase(extended_card_registry, card_instance_factory) -> GameState:
    """Game state in MAIN phase for testing main phase actions.

    - Turn 2, player1's turn, MAIN phase
    - Player1: Pikachu active (with 1 lightning energy), Charmander on bench, cards in hand
    - Player2: Raichu active
    """
    player1 = PlayerState(player_id="player1")
    player2 = PlayerState(player_id="player2")

    # Player 1 setup - active with energy, bench pokemon, cards in hand
    pikachu = card_instance_factory("pikachu_base_001", turn_played=1)
    # Attach energy as a CardInstance - energy is stored directly on the Pokemon
    energy = card_instance_factory("lightning_energy_001", instance_id="energy_lightning_1")
    pikachu.attach_energy(energy)
    player1.active.add(pikachu)
    player1.bench.add(card_instance_factory("charmander_base_001", turn_played=1))

    # Cards in hand: evolution card, energy, trainer
    player1.hand.add(card_instance_factory("raichu_base_001", instance_id="hand_raichu"))
    player1.hand.add(card_instance_factory("charmeleon_base_001", instance_id="hand_charmeleon"))
    player1.hand.add(card_instance_factory("lightning_energy_001", instance_id="hand_energy"))
    player1.hand.add(card_instance_factory("potion_base_001", instance_id="hand_potion"))
    player1.hand.add(card_instance_factory("professor_oak_001", instance_id="hand_supporter"))
    player1.hand.add(card_instance_factory("pokemon_center_001", instance_id="hand_stadium"))
    player1.hand.add(card_instance_factory("pikachu_base_001", instance_id="hand_basic"))

    # Energy in energy zone (for Pokemon Pocket style)
    player1.energy_zone.add(
        card_instance_factory("lightning_energy_001", instance_id="zone_energy")
    )

    # Some deck cards
    for i in range(10):
        player1.deck.add(card_instance_factory("pikachu_base_001", instance_id=f"deck_{i}"))

    # Player 2 setup
    player2.active.add(card_instance_factory("raichu_base_001", turn_played=1))
    for i in range(10):
        player2.deck.add(card_instance_factory("pikachu_base_001", instance_id=f"p2_deck_{i}"))

    return GameState(
        game_id="test_main_phase",
        rules=RulesConfig(),
        card_registry=extended_card_registry,
        players={"player1": player1, "player2": player2},
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=2,
        phase=TurnPhase.MAIN,
        first_turn_completed=True,
    )


@pytest.fixture
def game_in_attack_phase(extended_card_registry, card_instance_factory) -> GameState:
    """Game state in ATTACK phase for testing attack validation.

    - Turn 2, player1's turn, ATTACK phase
    - Player1: Pikachu active with enough energy for Thunder Shock
    - Player2: Raichu active
    """
    player1 = PlayerState(player_id="player1")
    player2 = PlayerState(player_id="player2")

    # Player 1 - Pikachu with 1 lightning energy (enough for Thunder Shock)
    pikachu = card_instance_factory("pikachu_base_001", turn_played=1)
    # Attach energy as a CardInstance - energy is stored directly on the Pokemon
    energy = card_instance_factory("lightning_energy_001", instance_id="energy_lightning_1")
    pikachu.attach_energy(energy)
    player1.active.add(pikachu)
    player1.bench.add(card_instance_factory("charmander_base_001", turn_played=1))

    for i in range(10):
        player1.deck.add(card_instance_factory("pikachu_base_001", instance_id=f"deck_{i}"))

    # Player 2
    player2.active.add(card_instance_factory("raichu_base_001", turn_played=1))

    return GameState(
        game_id="test_attack_phase",
        rules=RulesConfig(),
        card_registry=extended_card_registry,
        players={"player1": player1, "player2": player2},
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=2,
        phase=TurnPhase.ATTACK,
        first_turn_completed=True,
    )


@pytest.fixture
def game_in_setup_phase(extended_card_registry, card_instance_factory) -> GameState:
    """Game state in SETUP phase for testing setup actions.

    - Turn 0, SETUP phase
    - Both players have empty zones but basic pokemon in hand
    """
    player1 = PlayerState(player_id="player1")
    player2 = PlayerState(player_id="player2")

    # Player 1 - basic pokemon in hand for setup
    player1.hand.add(card_instance_factory("pikachu_base_001", instance_id="p1_hand_basic1"))
    player1.hand.add(card_instance_factory("charmander_base_001", instance_id="p1_hand_basic2"))

    # Player 2 - basic pokemon in hand
    player2.hand.add(card_instance_factory("pikachu_base_001", instance_id="p2_hand_basic1"))

    return GameState(
        game_id="test_setup",
        rules=RulesConfig(),
        card_registry=extended_card_registry,
        players={"player1": player1, "player2": player2},
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=0,
        phase=TurnPhase.SETUP,
        first_turn_completed=False,
    )


@pytest.fixture
def game_first_turn(extended_card_registry, card_instance_factory) -> GameState:
    """Game state on the first turn for testing first-turn restrictions.

    - Turn 1, player1's turn, MAIN phase
    - First turn restrictions apply
    """
    player1 = PlayerState(player_id="player1")
    player2 = PlayerState(player_id="player2")

    # Player 1 - just placed basic, has cards in hand
    player1.active.add(card_instance_factory("pikachu_base_001", turn_played=1))
    player1.hand.add(card_instance_factory("lightning_energy_001", instance_id="hand_energy"))
    player1.hand.add(card_instance_factory("raichu_base_001", instance_id="hand_raichu"))
    player1.hand.add(card_instance_factory("professor_oak_001", instance_id="hand_supporter"))

    for i in range(10):
        player1.deck.add(card_instance_factory("pikachu_base_001", instance_id=f"deck_{i}"))

    # Player 2
    player2.active.add(card_instance_factory("raichu_base_001", turn_played=1))

    return GameState(
        game_id="test_first_turn",
        rules=RulesConfig(),
        card_registry=extended_card_registry,
        players={"player1": player1, "player2": player2},
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=1,
        phase=TurnPhase.MAIN,
        first_turn_completed=False,  # Still first turn
    )


@pytest.fixture
def game_with_forced_action(extended_card_registry, card_instance_factory) -> GameState:
    """Game state with a forced action pending.

    - Player2's active was knocked out, must select new active
    - Player1 just attacked and knocked out player2's active
    """
    from app.core.models.game_state import ForcedAction

    player1 = PlayerState(player_id="player1")
    player2 = PlayerState(player_id="player2")

    # Player 1 - active pokemon
    player1.active.add(card_instance_factory("pikachu_base_001", turn_played=1))

    # Player 2 - no active (knocked out), but has bench
    player2.bench.add(card_instance_factory("charmander_base_001", instance_id="p2_bench1"))
    player2.bench.add(card_instance_factory("pikachu_base_001", instance_id="p2_bench2"))

    game = GameState(
        game_id="test_forced_action",
        rules=RulesConfig(),
        card_registry=extended_card_registry,
        players={"player1": player1, "player2": player2},
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=3,
        phase=TurnPhase.ATTACK,
        first_turn_completed=True,
        forced_actions=[
            ForcedAction(
                player_id="player2",
                action_type="select_active",
                reason="Active Pokemon was knocked out",
            )
        ],
    )

    return game


@pytest.fixture
def game_over_state(extended_card_registry, card_instance_factory) -> GameState:
    """Game state where the game is over.

    - Player1 has won
    """
    from app.core.enums import GameEndReason

    player1 = PlayerState(player_id="player1")
    player2 = PlayerState(player_id="player2")

    player1.active.add(card_instance_factory("pikachu_base_001"))
    player1.score = 4  # Won!

    return GameState(
        game_id="test_game_over",
        rules=RulesConfig(),
        card_registry=extended_card_registry,
        players={"player1": player1, "player2": player2},
        turn_order=["player1", "player2"],
        current_player_id="player1",
        turn_number=10,
        phase=TurnPhase.END,
        first_turn_completed=True,
        winner_id="player1",
        end_reason=GameEndReason.PRIZES_TAKEN,
    )
