"""
MTG Rules Engine - Main Rules Engine Module

Core rules engine for an online Magic: The Gathering application.
Enforces rule compliance during gameplay by validating:
  - Card casting (type, mana cost, timing)
  - Creature combat (attackers, blockers, damage assignment)
  - Spell resolution (targets, costs, effects)
  - Zone transitions (enters/leaves battlefield, stack)
  - Keyword ability interactions
  - State-based actions (lethal damage, legend rules)

Built on the hardcoded keyword database from keywords_db.py
and the validator from keyword_validator.py.
"""

from .keywords_db import (
    KEYWORD_ABILITIES,
    KEYWORD_ACTIONS,
    KEYWORD_VARIANTS,
    KEYWORD_TYPES,
    RULES_INDEX,
    get_keyword_definition,
    get_all_keywords,
)
from .keyword_validator import KeywordValidator, KeywordValidationError


# =============================================================================
# DATA MODELS
# =============================================================================

class CardType:
    """Card types in Magic: The Gathering."""
    CREATURE = "creature"
    SPELL = "spell"
    LAND = "land"
    ENCHANTMENT = "enchantment"
    ARTIFACT = "artifact"
    PLANEWALKER = "planeswalker"
    INSTANT = "instant"
    SORCERY = "sorcery"
    BATTLE = "battle"
    CONSPIRACY = "conspiracy"
    SCHEME = "scheme"
    PLANE = "plane"
    PHENOMENON = "phenomenon"
    VANGUARD = "vanguard"
    SAGA = "saga"
    OMEGA = "omega"
    CASE = "case"
    DUNGEON = "dungeon"
    ROOM = "room"
    DOOR = "door"


class CardTypeGroup:
    """Groups of card types."""
    CREATURES = {CardType.CREATURE}
    PERMANENTS = {
        CardType.CREATURE,
        CardType.LAND,
        CardType.ENCHANTMENT,
        CardType.ARTIFACT,
        CardType.PLANEWALKER,
    }
    SPELLS = {CardType.INSTANT, CardType.SORCERY}
    PERMANENT_SPELLS = {CardType.LAND, CardType.ENCHANTMENT, CardType.ARTIFACT, CardType.PLANEWALKER}


class Zone:
    """Game zones."""
    HAND = "hand"
    LIBRARY = "library"
    EXILE = "exile"
    GRAVEYARD = "graveyard"
    COMMAND_ZONE = "command_zone"
    BATTLEFIELD = "battlefield"
    STACK = "stack"
    PLANAR_DECK = "planar_deck"
    SCHEME_DECK = "scheme_deck"
    DUNGEON = "dungeon"


class Phase:
    """Turn phases."""
    UNTAP = "untap"
    DRAW = "draw"
    MAIN_PHASE = "main_phase"
    PRECOMBAT = "precombat"
    COMBAT = "combat"
    BEGINNING_COMBAT = "beginning_combat"
    DECLARE_ATTACKERS = "declare_attackers"
    DECLARE_BLOCKERS = "declare_blockers"
    COMBAT_DAMAGE = "combat_damage"
    END_COMBAT = "end_combat"
    END_PHASE = "end_phase"
    END_STEP = "end_step"
    CLEANUP = "cleanup"


class ZoneTransitionEvent:
    """Represents an object moving between zones."""
    def __init__(self, object_id: str, from_zone: str, to_zone: str, object_type: str = None):
        self.object_id = object_id
        self.from_zone = from_zone
        self.to_zone = to_zone
        self.object_type = object_type

    def is_enters_battlefield(self) -> bool:
        return self.to_zone == Zone.BATTLEFIELD

    def is_leaves_battlefield(self) -> bool:
        return self.from_zone == Zone.BATTLEFIELD


class GameAction:
    """Represents a game action that may need validation."""
    def __init__(self, action_type: str, details: dict = None):
        self.action_type = action_type
        self.details = details or {}

    def __repr__(self):
        return f"GameAction({self.action_type}, {self.details})"


# =============================================================================
# ZONE MANAGEMENT
# =============================================================================

class ZoneManager:
    """Manages object positions in game zones."""
    
    def __init__(self):
        self.zones = {zone: [] for zone in Zone.__dict__.values() if not zone.startswith("_")}
    
    def add_object(self, object_id: str, zone: str, object_type: str = None):
        """Add an object to a zone."""
        if zone not in self.zones:
            raise ValueError(f"Invalid zone: {zone}")
        self.zones[zone].append({
            "id": object_id,
            "type": object_type,
            "added_at": len(self.zones[zone]),
        })
    
    def remove_object(self, object_id: str, zone: str) -> dict | None:
        """Remove an object from a zone. Returns the object data or None."""
        if zone not in self.zones:
            return None
        for i, obj in enumerate(self.zones[zone]):
            if obj["id"] == object_id:
                return self.zones[zone].pop(i)
        return None
    
    def get_objects_in_zone(self, zone: str) -> list[dict]:
        """Get all objects in a zone."""
        return self.zones.get(zone, [])
    
    def get_object(self, object_id: str) -> dict | None:
        """Find an object by ID across all zones."""
        for zone_objs in self.zones.values():
            for obj in zone_objs:
                if obj["id"] == object_id:
                    return obj, zone
        return None
    
    def transition(self, object_id: str, from_zone: str, to_zone: str, object_type: str = None) -> ZoneTransitionEvent:
        """
        Transition an object between zones.
        
        Returns:
            ZoneTransitionEvent with the transition details.
        """
        obj = self.remove_object(object_id, from_zone)
        if obj is None:
            raise ValueError(f"Object {object_id} not found in zone {from_zone}")
        
        self.add_object(object_id, to_zone, object_type)
        return ZoneTransitionEvent(object_id, from_zone, to_zone, object_type)


# =============================================================================
# CARD PARSE AND VALIDATE
# =============================================================================

class CardParser:
    """
    Parse and validate card data.
    
    Extracts card type, mana cost, keywords, and abilities from card text.
    Validates the card against MTG rules.
    """
    
    def __init__(self):
        self.validator = KeywordValidator()
    
    def parse_card(self, card_data: dict) -> dict:
        """
        Parse and validate card data.
        
        Args:
            card_data: Dictionary with card information (name, type, text, mana_cost, etc.)
            
        Returns:
            Validated card dictionary.
            
        Raises:
            KeywordValidationError: If the card has invalid keyword usage.
        """
        validated = {
            "id": card_data.get("id", "unknown"),
            "name": card_data.get("name", "Unknown"),
            "type": card_data.get("type", "unknown").lower(),
            "mana_cost": card_data.get("mana_cost", ""),
            "text": card_data.get("text", ""),
            "keywords": self._extract_keywords(card_data.get("text", "")),
            "abilities": self._extract_abilities(card_data.get("text", "")),
            "is_valid": True,
            "errors": [],
        }
        
        # Validate card type
        if validated["type"] not in CardTypeGroup.CREATURES and validated["type"] not in CardTypeGroup.SPELLS:
            validated["is_valid"] = False
            validated["errors"].append(f"Invalid card type: {validated['type']}")
        
        # Validate keywords
        if validated["text"]:
            validation_results = self.validator.validate_card_text(validated["text"])
            for result in validation_results:
                if not result["valid"]:
                    validated["is_valid"] = False
                    validated["errors"].append(
                        f"Invalid keyword usage: {result['keyword']}"
                    )
        
        return validated
    
    def _extract_keywords(self, text: str) -> list[str]:
        """Extract keywords from card text."""
        keywords = set()
        for kw in get_all_keywords():
            if kw.lower() in text.lower():
                keywords.add(kw)
        return sorted(keywords)
    
    def _extract_abilities(self, text: str) -> list[dict]:
        """Extract abilities from card text."""
        abilities = []
        # Simple extraction - in production, use NLP/parsing
        for line in text.split("\n"):
            line = line.strip()
            if line:
                # Check for keyword abilities
                for kw, data in KEYWORD_ABILITIES.items():
                    if kw in line.lower():
                        abilities.append({
                            "keyword": kw,
                            "text": line,
                            "definition": data["definition"],
                            "rule": data["rule"],
                            "type": data["type"],
                        })
        return abilities
    
    def validate_casting(self, card: dict, player_state: dict) -> dict:
        """
        Validate if a card can be cast.
        
        Args:
            card: The validated card dictionary.
            player_state: Dictionary with player's current state (mana, life, etc.)
            
        Returns:
            Validation result with errors and warnings.
        """
        result = {
            "can_cast": True,
            "errors": [],
            "warnings": [],
        }
        
        # Validate card type for casting
        if card["type"] not in CardTypeGroup.SPELLS and card["type"] not in CardTypeGroup.PERMANENT_SPELLS:
            result["can_cast"] = False
            result["errors"].append(f"Card type '{card['type']}' cannot be cast")
            return result
        
        # Validate timing (instant vs sorcery)
        if card["type"] == CardType.SORCERY:
            if "main_phase" not in player_state.get("current_phase", ""):
                result["can_cast"] = False
                result["errors"].append("Sorceries can only be cast during the main phase")
        
        # Validate mana cost
        mana_cost = card.get("mana_cost", "")
        if mana_cost:
            required_mana = self._parse_mana_cost(mana_cost)
            available_mana = player_state.get("available_mana", {})
            
            if required_mana and not self._can_pay_cost(required_mana, available_mana):
                result["can_cast"] = False
                result["errors"].append(
                    f"Insufficient mana. Required: {required_mana}, Available: {available_mana}"
                )
        
        return result
    
    def _parse_mana_cost(self, cost: str) -> dict:
        """Parse a mana cost string into a structured format."""
        # Simple parser - production would use regex
        costs = {"W": 0, "U": 0, "B": 0, "R": 0, "G": 0, "C": 0, "E": 0, "X": 0}
        import re
        for match in re.finditer(r"\{([WUBRGCEEXS]|[\d]+)\}", cost):
            sym = match.group(1)
            if sym in costs:
                costs[sym] += 1
            elif sym.isdigit():
                costs["C"] += int(sym)
            elif sym == "E":
                costs["E"] += 1
        return {k: v for k, v in costs.items() if v > 0}
    
    def _can_pay_cost(self, required: dict, available: dict) -> bool:
        """Check if a mana cost can be paid."""
        total_required = sum(required.values())
        total_available = sum(available.values())
        return total_available >= total_required


# =============================================================================
# COMBAT RESOLVER
# =============================================================================

class CombatResolver:
    """
    Resolves combat phase according to MTG rules.
    
    Handles:
    - Attacker declaration
    - Blocker declaration
    - Combat damage assignment
    - Death resolution (deathtouch, lethal damage)
    """
    
    def __init__(self):
        self.validator = KeywordValidator()
        self.zone_manager = ZoneManager()
    
    def resolve_turn(self, game_state: dict) -> dict:
        """
        Resolve a full turn.
        
        Args:
            game_state: Dictionary with game state information.
            
        Returns:
            Turn resolution results.
        """
        results = {
            "phases_resolved": [],
            "actions_taken": [],
            "errors": [],
        }
        
        # Untap phase
        results["phases_resolved"].append("untap")
        results["actions_taken"].append(self._untap_phase(game_state))
        
        # Draw phase
        results["phases_resolved"].append("draw")
        results["actions_taken"].append(self._draw_phase(game_state))
        
        # Main phase
        results["phases_resolved"].append("main_phase")
        results["actions_taken"].append(self._main_phase(game_state))
        
        # Pre-combat
        results["phases_resolved"].append("precombat")
        
        # Combat phase
        if game_state.get("has_combat"):
            results["phases_resolved"].append("combat")
            combat_result = self._resolve_combat(game_state)
            results["actions_taken"].append(combat_result)
        
        # End phase
        results["phases_resolved"].append("end_phase")
        results["actions_taken"].append(self._end_phase(game_state))
        
        return results
    
    def _untap_phase(self, game_state: dict) -> dict:
        """Resolve the untap phase."""
        return {"action": "untap", "untapped": game_state.get("untapped_permanents", [])}
    
    def _draw_phase(self, game_state: dict) -> dict:
        """Resolve the draw phase."""
        draw_amount = game_state.get("draw_amount", 1)
        return {"action": "draw", "drawn": draw_amount}
    
    def _main_phase(self, game_state: dict) -> dict:
        """Resolve the main phase (player actions)."""
        # Player takes actions here - simplified
        return {"action": "main_phase", "actions": game_state.get("player_actions", [])}
    
    def _resolve_combat(self, game_state: dict) -> dict:
        """Resolve the combat phase."""
        result = {
            "action": "combat",
            "attackers": [],
            "blockers": [],
            "damage_assigned": [],
            "deaths": [],
            "errors": [],
        }
        
        # Get attackers and blockers
        attackers = game_state.get("attackers", [])
        blockers = game_state.get("blockers", [])
        
        # Validate attackers
        for attacker in attackers:
            validation = self._validate_attacker(attacker, game_state)
            if validation["valid"]:
                result["attackers"].append(attacker)
            else:
                result["errors"].extend(validation["errors"])
        
        # Validate blockers
        for blocker in blockers:
            validation = self._validate_blocker(blocker, game_state)
            if validation["valid"]:
                result["blockers"].append(blocker)
            else:
                result["errors"].extend(validation["errors"])
        
        # Assign combat damage
        result["damage_assigned"] = self._assign_damage(attackers, blockers, game_state)
        
        # Process deaths
        result["deaths"] = self._process_deaths(game_state)
        
        return result
    
    def _validate_attacker(self, attacker: dict, game_state: dict) -> dict:
        """Validate an attacker."""
        result = {"valid": True, "errors": []}
        
        # Check for haste (summoning sickness)
        if not attacker.get("haste") and not attacker.get("untapped"):
            result["valid"] = False
            result["errors"].append(f"Attacker {attacker.get('id')} has summoning sickness")
        
        # Check if attacker is a creature
        if attacker.get("type") != "creature":
            result["valid"] = False
            result["errors"].append(f"Attacker {attacker.get('id')} is not a creature")
        
        return result
    
    def _validate_blocker(self, blocker: dict, game_state: dict) -> dict:
        """Validate a blocker."""
        result = {"valid": True, "errors": []}
        
        # Check if blocker is a creature
        if blocker.get("type") != "creature":
            result["valid"] = False
            result["errors"].append(f"Blocker {blocker.get('id')} is not a creature")
            return result
        
        # Check evasion abilities
        attackers = game_state.get("attackers", [])
        blocker_evasion = blocker.get("evasion", [])
        
        for attacker in attackers:
            attacker_evasion = attacker.get("evasion", [])
            
            if not self._blocker_can_block(blocker_evasion, attacker_evasion):
                result["valid"] = False
                result["errors"].append(
                    f"Blocker {blocker.get('id')} can't block attacker {attacker.get('id')} "
                    f"due to evasion abilities"
                )
                break
        
        return result
    
    def _blocker_can_block(self, blocker_evasion: list[str], attacker_evasion: list[str]) -> bool:
        """Check if a blocker can block an attacker based on evasion abilities."""
        if not attacker_evasion:
            return True
        
        for ev in attacker_evasion:
            if ev == "flying":
                if "flying" not in blocker_evasion and "reach" not in blocker_evasion:
                    return False
            elif ev == "shadow":
                if "shadow" not in blocker_evasion:
                    return False
            elif ev == "horsemanship":
                if "horsemanship" not in blocker_evasion:
                    return False
            elif ev == "intimidate":
                if "intimidate" not in blocker_evasion:
                    return False
            elif ev == "flanking":
                if "flanking" not in blocker_evasion:
                    return False
            elif ev == "skulk":
                # Skulk: can't be blocked by creatures with greater power
                # We don't have power info here, so we assume it can block
                pass
            elif ev == "menace":
                if len(blocker_evasion) < 2:
                    return False
        
        return True
    
    def _assign_damage(self, attackers: list[dict], blockers: list[dict], game_state: dict) -> list[dict]:
        """Assign combat damage."""
        damage_assigned = []
        
        for attacker in attackers:
            attacker_power = attacker.get("power", 0)
            attacker_id = attacker.get("id")
            
            # Check for trample
            has_trample = "trample" in attacker.get("keywords", [])
            trample_over_pws = "trample_over_planeswalkers" in attacker.get("keywords", [])
            
            # Assign damage to blockers first
            for blocker in blockers:
                blocker_id = blocker.get("id")
                blocker_toughness = blocker.get("toughness", 0)
                damage_to_blocker = min(attacker_power, blocker_toughness)
                
                damage_assigned.append({
                    "attacker_id": attacker_id,
                    "target_id": blocker_id,
                    "damage": damage_to_blocker,
                    "type": "combat",
                })
                
                attacker_power -= damage_to_blocker
                if attacker_power <= 0:
                    break
            
            # Assign remaining damage to defender (trample)
            if attacker_power > 0 and (has_trample or trample_over_pws):
                defender_life = game_state.get("defender_life", 20)
                damage_to_defender = min(attacker_power, defender_life)
                damage_assigned.append({
                    "attacker_id": attacker_id,
                    "target_id": "defender",
                    "damage": damage_to_defender,
                    "type": "combat",
                })
        
        return damage_assigned
    
    def _process_deaths(self, game_state: dict) -> list[str]:
        """Process state-based death resolution."""
        deaths = []
        
        # Check for lethal damage
        for damage in game_state.get("damage_assigned", []):
            target = damage.get("target_id")
            amount = damage.get("damage", 0)
            
            if target == "defender":
                # Player takes damage
                game_state["defender_life"] -= amount
                if game_state["defender_life"] <= 0:
                    deaths.append("defender")
            else:
                # Creature takes damage
                target_info = game_state.get("targets", {}).get(target)
                if target_info:
                    toughness = target_info.get("toughness", 0)
                    damage_marked = target_info.get("damage_marked", 0) + amount
                    
                    # Check for deathtouch
                    attacker_id = damage.get("attacker_id")
                    attacker_has_deathtouch = any(
                        k in game_state.get("attackers", {}).get(attacker_id, {}).get("keywords", [])
                        for k in ["deathtouch"]
                    )
                    
                    if attacker_has_deathtouch:
                        # Deathtouch: any nonzero damage is lethal
                        if amount > 0:
                            deaths.append(target)
                    else:
                        # Normal damage: check for lethal
                        if damage_marked >= toughness:
                            deaths.append(target)
        
        return deaths
    
    def _end_phase(self, game_state: dict) -> dict:
        """Resolve the end phase."""
        return {"action": "end_phase", "life": game_state.get("defender_life", 20)}


# =============================================================================
# MAIN RULES ENGINE
# =============================================================================

class RulesEngine:
    """
    Main rules engine for Magic: The Gathering.
    
    Provides high-level rule enforcement by composing:
    - CardParser for card validation
    - ZoneManager for zone tracking
    - CombatResolver for combat resolution
    - KeywordValidator for keyword validation
    
    Usage:
        engine = RulesEngine()
        result = engine.validate_action(card, player_state, action)
    """
    
    def __init__(self):
        self.validator = KeywordValidator()
        self.card_parser = CardParser()
        self.zone_manager = ZoneManager()
        self.combat_resolver = CombatResolver()
    
    def validate_action(self, card: dict, player_state: dict, action: GameAction) -> dict:
        """
        Validate a game action.
        
        Args:
            card: The validated card dictionary.
            player_state: Dictionary with player's current state.
            action: The GameAction to validate.
            
        Returns:
            Validation result dictionary.
        """
        result = {
            "valid": True,
            "errors": [],
            "warnings": [],
            "action": action.action_type,
        }
        
        # Validate based on action type
        if action.action_type == "cast":
            result = self._validate_cast(card, player_state, result)
        elif action.action_type == "attack":
            result = self._validate_attack(card, player_state, result)
        elif action.action_type == "block":
            result = self._validate_block(card, player_state, result)
        elif action.action_type == "resolve_combat":
            result = self._validate_combat_resolution(player_state, result)
        elif action.action_type == "zone_transition":
            result = self._validate_zone_transition(card, player_state, result)
        else:
            result["valid"] = False
            result["errors"].append(f"Unknown action type: {action.action_type}")
        
        return result
    
    def _validate_cast(self, card: dict, player_state: dict, result: dict) -> dict:
        """Validate a spell casting action."""
        cast_result = self.card_parser.validate_casting(card, player_state)
        
        if not cast_result["can_cast"]:
            result["valid"] = False
            result["errors"].extend(cast_result["errors"])
            result["warnings"].extend(cast_result.get("warnings", []))
        
        # Validate targets
        if card.get("targets"):
            for target in card["targets"]:
                if not self.validator.is_valid_keyword(target):
                    result["valid"] = False
                    result["errors"].append(f"Invalid target keyword: {target}")
        
        return result
    
    def _validate_attack(self, card: dict, player_state: dict, result: dict) -> dict:
        """Validate an attack action."""
        # Check if card is a creature
        if card["type"] != "creature":
            result["valid"] = False
            result["errors"].append("Only creatures can attack")
            return result
        
        # Check summoning sickness
        if not card.get("haste") and not card.get("untapped"):
            result["valid"] = False
            result["errors"].append("Creature has summoning sickness")
        
        return result
    
    def _validate_block(self, card: dict, player_state: dict, result: dict) -> dict:
        """Validate a block action."""
        if card["type"] != "creature":
            result["valid"] = False
            result["errors"].append("Only creatures can block")
            return result
        
        # Check evasion abilities
        attacker = player_state.get("attacker", {})
        attacker_evasion = attacker.get("evasion", [])
        blocker_evasion = card.get("evasion", [])
        
        if not self.combat_resolver._blocker_can_block(blocker_evasion, attacker_evasion):
            result["valid"] = False
            result["errors"].append("Blocker can't block attacker due to evasion")
        
        return result
    
    def _validate_combat_resolution(self, player_state: dict, result: dict) -> dict:
        """Validate combat resolution."""
        combat_result = self.combat_resolver.resolve_turn(player_state)
        
        if combat_result.get("errors"):
            result["valid"] = False
            result["errors"].extend(combat_result["errors"])
        
        return result
    
    def _validate_zone_transition(self, card: dict, player_state: dict, result: dict) -> dict:
        """Validate a zone transition action."""
        from_zone = player_state.get("from_zone")
        to_zone = player_state.get("to_zone")
        
        if not from_zone or not to_zone:
            result["valid"] = False
            result["errors"].append("Zone transition requires from_zone and to_zone")
            return result
        
        # Validate transition
        valid_transitions = {
            (Zone.HAND, Zone.BATTLEFIELD): CardTypeGroup.PERMANENT_SPELLS,
            (Zone.LIBRARY, Zone.HAND): set(),
            (Zone.HAND, Zone.LIBRARY): set(),
            (Zone.BATTLEFIELD, Zone.GRAVEYARD): set(),
            (Zone.GRAVEYARD, Zone.HAND): set(),
            (Zone.BATTLEFIELD, Zone.EXILE): set(),
            (Zone.EXILE, Zone.BATTLEFIELD): set(),
        }
        
        transition_key = (from_zone, to_zone)
        if transition_key not in valid_transitions:
            result["valid"] = False
            result["errors"].append(f"Invalid zone transition: {from_zone} -> {to_zone}")
            return result
        
        return result
    
    def get_rules_index(self) -> dict:
        """Get the rules index for reference."""
        return RULES_INDEX


# =============================================================================
# GAME STATE MANAGER
# =============================================================================

class GameState:
    """
    Manages the state of a Magic: The Gathering game.
    
    Tracks:
    - Players and their resources
    - Card zones (hand, battlefield, graveyard, etc.)
    - Stack of pending effects
    - Current phase and turn
    - Combat state
    """
    
    def __init__(self, player_count: int = 2):
        self.player_count = player_count
        self.current_player = 0
        self.current_phase = Phase.UNTAP
        self.stack = []
        self.zone_manager = ZoneManager()
        self.combat_state = {
            "attackers": [],
            "blockers": [],
            "damage_assigned": [],
            "phase": None,
        }
        self.game_state = {
            "players": self._init_players(),
            "has_combat": False,
            "defender_life": 20,
            "targets": {},
        }
    
    def _init_players(self) -> list[dict]:
        """Initialize player states."""
        players = []
        for i in range(self.player_count):
            players.append({
                "id": i,
                "life": 20,
                "mana": 0,
                "mana_available": 0,
                "hand": [],
                "zone": Zone.HAND,
            })
        return players
    
    def advance_phase(self) -> str:
        """Advance to the next phase."""
        phase_order = [
            Phase.UNTAP,
            Phase.DRAW,
            Phase.MAIN_PHASE,
            Phase.PRECOMBAT,
            Phase.BEGINNING_COMBAT,
            Phase.DECLARE_ATTACKERS,
            Phase.DECLARE_BLOCKERS,
            Phase.COMBAT_DAMAGE,
            Phase.END_COMBAT,
            Phase.END_PHASE,
            Phase.END_STEP,
            Phase.CLEANUP,
        ]
        
        current_idx = phase_order.index(self.current_phase)
        next_idx = (current_idx + 1) % len(phase_order)
        self.current_phase = phase_order[next_idx]
        return self.current_phase
    
    def get_player_state(self, player_id: int) -> dict:
        """Get a player's state."""
        return self.game_state["players"][player_id]
    
    def set_combat_state(self, state: dict):
        """Set the combat phase state."""
        self.combat_state.update(state)
        self.game_state["has_combat"] = True
    
    def get_engine(self) -> RulesEngine:
        """Get the rules engine for this game state."""
        return RulesEngine()
