"""Configuration types for Lattice."""

from __future__ import annotations

from dataclasses import dataclass, field

from deal import post


@dataclass(frozen=True)
class CompilerConfig:
    """Compiler configuration from config.toml [compiler] section.

    Model uses litellm format: "provider/model".

    >>> cfg = CompilerConfig(
    ...     model="openrouter/google/gemini-3-flash-preview",
    ...     api_key_env="OPENROUTER_API_KEY",
    ...     batch_cap=30,
    ... )
    >>> cfg.model
    'openrouter/google/gemini-3-flash-preview'
    """

    model: str
    api_key_env: str
    api_key: str | None = None
    batch_cap: int = 30
    base_url: str | None = None


@dataclass(frozen=True)
class EmbeddingConfig:
    """Embedding configuration from config.toml [embedding] section.

    Model uses litellm format: "provider/model".

    >>> cfg = EmbeddingConfig(
    ...     model="ollama/nomic-embed-text",
    ...     dimensions=768,
    ... )
    >>> cfg.dimensions
    768
    """

    model: str
    dimensions: int = 768
    api_key_env: str = ""
    api_key: str | None = None
    base_url: str | None = None


@dataclass(frozen=True)
class ThresholdsConfig:
    """Token threshold configuration from config.toml [thresholds] section.

    >>> cfg = ThresholdsConfig(warn_tokens=3000, alert_tokens=5000)
    >>> cfg.warn_tokens
    3000
    >>> cfg.per_session_tokens
    4000
    """

    warn_tokens: int = 3000
    alert_tokens: int = 5000
    per_session_tokens: int = 4000  # max tokens per session fed to Compiler


@dataclass(frozen=True)
class SafetyConfig:
    """Safety configuration from config.toml [safety] section.

    >>> cfg = SafetyConfig(
    ...     auto_apply=True,
    ...     backup_keep=10,
    ...     secret_patterns=[r"(?i)api[_-]?key"],
    ... )
    >>> cfg.auto_apply
    True
    """

    auto_apply: bool = True
    backup_keep: int = 10
    secret_patterns: list[str] = field(default_factory=list)


@dataclass(frozen=True)
class CaptureConfig:
    """Capture mode configuration from config.toml [capture] section.

    Controls whether the MCP server exposes the log_turn tool for active
    capture mode. When a hook/plugin captures data via `lattice ingest`,
    the MCP server should be passive (read-only for store.db).

    Mode options:
    - "passive": MCP server is read-only, log_turn tool not registered
    - "active": MCP server can log turns, log_turn tool registered

    >>> cfg = CaptureConfig()
    >>> cfg.mode
    'passive'
    >>> cfg = CaptureConfig(mode="active")
    >>> cfg.mode
    'active'
    """

    mode: str = "passive"

    @post(lambda result: isinstance(result, bool))
    def is_active(self) -> bool:
        """Return True if capture mode is active.

        >>> CaptureConfig().is_active()
        False
        >>> CaptureConfig(mode="active").is_active()
        True
        """
        return self.mode == "active"


@dataclass(frozen=True)
class Layer1Config:
    """Layer 1 summarization configuration from config.toml [layer1] section.

    Optional local model summarization for large sessions.
    Uses Ollama for local inference (zero API cost).

    >>> cfg = Layer1Config()
    >>> cfg.enabled
    False
    >>> cfg = Layer1Config(enabled=True, model="llama3.2:3b")
    >>> cfg.model
    'llama3.2:3b'
    """

    enabled: bool = False
    model: str = "llama3.2:3b"
    min_tokens: int = 1000000  # Only summarize sessions > 1M tokens
    ollama_host: str = "http://localhost:11434"


@dataclass(frozen=True)
class Config:
    """Complete configuration from config.toml.

    Embedding is optional — when None, search uses FTS5-only (no vector).
    Capture is optional — defaults to passive mode.
    Layer1 is optional — defaults to disabled.

    >>> cfg = Config(
    ...     compiler=CompilerConfig(
    ...         model="openrouter/gemini",
    ...         api_key_env="KEY",
    ...     ),
    ... )
    >>> cfg.compiler.model
    'openrouter/gemini'
    >>> cfg.embedding is None
    True
    >>> cfg.capture.mode
    'passive'
    >>> cfg.layer1.enabled
    False
    """

    compiler: CompilerConfig
    embedding: EmbeddingConfig | None = None
    thresholds: ThresholdsConfig = field(default_factory=ThresholdsConfig)
    safety: SafetyConfig = field(default_factory=SafetyConfig)
    capture: CaptureConfig = field(default_factory=CaptureConfig)
    layer1: Layer1Config = field(default_factory=Layer1Config)
