"""TierGate — runtime feature flag gate for Genesis agent tiers.

Determines what capabilities, tools, models, and budgets are available
based on the agent's product tier (BASIC, STANDARD, PRO, ENTERPRISE).

Default is ENTERPRISE — all existing code continues working unchanged.
"""

import logging
from typing import Optional

from .tier_config import load_tier_config, resolve_capabilities, parse_agent_frontmatter

logger = logging.getLogger("core.tiering.tier_gate")


class TierGate:
    """Runtime capability gate for Genesis product tiers.

    Usage:
        gate = TierGate("ENTERPRISE")
        if gate.has("native_voice"):
            start_voice_client()
        if gate.has("ide_access"):
            enable_file_writes()
    """

    TIER_ORDER = ["BASIC", "STANDARD", "PRO", "ENTERPRISE"]

    TIER_LEVEL = {name: idx for idx, name in enumerate(TIER_ORDER)}

    def __init__(self, tier_name: str = "ENTERPRISE", config_path: Optional[str] = None):
        tier_name = tier_name.upper()
        if tier_name not in self.TIER_ORDER:
            logger.warning(f"Unknown tier '{tier_name}', defaulting to ENTERPRISE")
            tier_name = "ENTERPRISE"

        self.tier_name = tier_name
        self._config = load_tier_config(config_path)
        self._tier_data = self._config.get("tiers", {}).get(self.tier_name, {})
        self._all_capabilities = resolve_capabilities(self.tier_name, self._config)

        logger.info(
            f"TierGate initialized: {self.tier_name} "
            f"({len(self._all_capabilities)} capabilities)"
        )

    def has(self, capability: str) -> bool:
        """Check if this tier includes the given capability."""
        return capability in self._all_capabilities

    def get_all_capabilities(self) -> set:
        """Return the full resolved set of capabilities for this tier."""
        return set(self._all_capabilities)

    def get_model_stack(self) -> dict:
        """Return the model selection for this tier."""
        return dict(self._tier_data.get("model_stack", {}))

    def get_budget_limits(self) -> dict:
        """Return budget constraints for this tier."""
        return {
            "daily_budget_usd": self._tier_data.get("daily_budget_usd", 1.0),
            "max_turns": self._tier_data.get("max_turns", 50),
        }

    def get_autonomy_level(self) -> int:
        """Return the default autonomy level (0=full auto, 3=advisory only)."""
        return self._tier_data.get("autonomy_level", 3)

    def get_tool_access(self) -> list:
        """Return the list of allowed Claude Code tools for this tier."""
        return list(self._tier_data.get("tool_access", []))

    def get_mcp_tools(self) -> list:
        """Return the list of allowed MCP tools for this tier.

        Returns a list of tool name patterns. "ALL" means unrestricted.
        Patterns with wildcards (e.g. "kg_*") match tool names by prefix.
        """
        mcp = self._tier_data.get("mcp_tools", [])
        if isinstance(mcp, str):
            return [mcp]
        return list(mcp)

    def get_domain_overlays(self) -> int:
        """Return allowed domain overlay count. -1 means unlimited."""
        return self._tier_data.get("domain_overlays", 0)

    def get_display_name(self) -> str:
        """Return the human-readable tier name."""
        return self._tier_data.get("display_name", self.tier_name)

    def get_agent_file(self) -> str:
        """Return the agent definition filename for this tier."""
        return self._tier_data.get("agent_file", "")

    def at_least(self, minimum_tier: str) -> bool:
        """Check if this tier is at or above the given tier level."""
        minimum_tier = minimum_tier.upper()
        if minimum_tier not in self.TIER_LEVEL:
            return False
        return self.TIER_LEVEL[self.tier_name] >= self.TIER_LEVEL[minimum_tier]

    def __repr__(self) -> str:
        return f"TierGate(tier={self.tier_name}, capabilities={len(self._all_capabilities)})"

    @classmethod
    def from_agent_definition(cls, agent_md_path: str) -> "TierGate":
        """Create a TierGate from a .claude/agents/*.md file's YAML frontmatter.

        Parses the 'tier' field from the frontmatter and initializes
        the gate with that tier name.
        """
        parsed = parse_agent_frontmatter(agent_md_path)
        tier_name = parsed["frontmatter"].get("tier", "ENTERPRISE")
        logger.info(f"TierGate.from_agent_definition: {agent_md_path} → tier={tier_name}")
        return cls(tier_name=tier_name)
