"""Variable resolver — interpolate {{var}} placeholders in flow definitions.

Resolution order:
  1. Flow-level parameters (passed at runtime)
  2. antiqa.json config values (flattened with dot notation)
  3. Environment variables
"""

from __future__ import annotations

import os
import re
from typing import Any

from antiqa.config.schema import AntiQAConfig

_VAR_RE = re.compile(r"\{\{\s*(\w[\w.]*)\s*\}\}")


def _flatten_config(config: AntiQAConfig) -> dict[str, str]:
    """Flatten the config into dot-notation keys for variable lookup."""
    flat: dict[str, str] = {
        "app_url": config.app_url,
        "llm.provider": config.llm.provider,
        "llm.model": config.llm.model,
        "jira.base_url": config.jira.base_url,
        "jira.project_key": config.jira.project_key,
        "jira.email": config.jira.email,
        "browser.type": config.browser.type,
    }
    return flat


class VariableResolver:
    """Resolve {{var}} placeholders in strings."""

    def __init__(
        self,
        config: AntiQAConfig | None = None,
        params: dict[str, str] | None = None,
    ) -> None:
        self._params = params or {}
        self._config_vars = _flatten_config(config) if config else {}

    def resolve_string(self, text: str) -> str:
        """Replace all {{var}} in *text* with resolved values."""
        def _replace(match: re.Match) -> str:
            key = match.group(1)
            # 1. Flow params
            if key in self._params:
                return self._params[key]
            # 2. Config values
            if key in self._config_vars:
                return self._config_vars[key]
            # 3. Environment variables
            env_val = os.environ.get(key)
            if env_val is not None:
                return env_val
            # Unresolved — leave as-is so it's visible in logs
            return match.group(0)

        return _VAR_RE.sub(_replace, text)

    def resolve_value(self, value: Any) -> Any:
        """Recursively resolve variables in strings, lists, and dicts."""
        if isinstance(value, str):
            return self.resolve_string(value)
        if isinstance(value, list):
            return [self.resolve_value(v) for v in value]
        if isinstance(value, dict):
            return {k: self.resolve_value(v) for k, v in value.items()}
        return value
