"""Configuration helpers -- env-var parsing and substitution."""

from __future__ import annotations

import logging
import os
from typing import Any

logger = logging.getLogger(__name__)

# Valid characters for environment variable names (after the leading letter/underscore)
_VAR_CHARS = frozenset("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_")


def env_bool(name: str, default: bool = False) -> bool:
    """Parse boolean environment variable."""
    v = os.getenv(name)
    if v is None:
        return default
    return v.strip().lower() in ("1", "true", "yes", "y", "on")


def env_int(name: str, default: int | None = None) -> int | None:
    """Parse integer environment variable."""
    v = os.getenv(name)
    if v is None:
        return default
    try:
        return int(v.strip())
    except ValueError:
        return default


def _substitute_env_string(text: str) -> str:
    """Single-pass parser for ${VAR} and ${VAR:-default} substitution.

    Scans character-by-character, emitting literals and resolving
    ``${...}`` references in one pass with clear error reporting.
    """
    result: list[str] = []
    i = 0
    n = len(text)

    while i < n:
        if text[i] == "$" and i + 1 < n and text[i + 1] == "{":
            i += 2  # skip ${

            var_start = i
            while i < n and text[i] in _VAR_CHARS:
                i += 1
            var_name = text[var_start:i]

            if not var_name:
                logger.warning("Empty variable name in substitution at position %d", var_start - 2)
                result.append("${")
                continue

            default: str | None = None
            if i + 1 < n and text[i] == ":" and text[i + 1] == "-":
                i += 2  # skip :-
                default_start = i
                while i < n and text[i] != "}":
                    i += 1
                default = text[default_start:i]

            if i >= n or text[i] != "}":
                logger.warning("Unclosed variable substitution: ${%s", var_name)
                result.append("${")
                result.append(var_name)
                if default is not None:
                    result.append(":-")
                    result.append(default)
                continue

            i += 1  # skip }

            env_value = os.getenv(var_name)
            if env_value is not None:
                result.append(env_value)
            elif default is not None:
                result.append(default)
            else:
                logger.warning("Environment variable %s not set (no default)", var_name)
        else:
            result.append(text[i])
            i += 1

    return "".join(result)


def substitute_env_vars(value: Any) -> Any:
    """Recursively substitute ${VAR} and ${VAR:-default} in strings."""
    if isinstance(value, str):
        return _substitute_env_string(value)
    if isinstance(value, dict):
        return {k: substitute_env_vars(v) for k, v in value.items()}
    if isinstance(value, list):
        return [substitute_env_vars(item) for item in value]
    return value
