"""
LLM configuration and API key resolution.
"""

from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional, Dict, Any
import os


@dataclass
class LLMConfig:
    """Configuration for an LLM adapter.

    Attributes:
        provider: Backend identifier (``"openrouter"`` or ``"claude-code"``).
        model: Model name / path sent to the provider.
        api_key: Resolved API key (may be ``None`` for CLI backends).
        api_base: Base URL for HTTP-based providers.
        claude_cli_path: Path to the ``claude`` CLI binary.
        timeout_seconds: Per-request timeout.
        max_retries: Number of retry attempts on transient errors.
        extra: Arbitrary provider-specific overrides.
    """

    provider: str = "openrouter"
    model: str = "anthropic/claude-sonnet-4"
    api_key: Optional[str] = None
    api_base: str = "https://openrouter.ai/api/v1"
    claude_cli_path: str = "claude"
    timeout_seconds: int = 300
    max_retries: int = 3
    extra: Dict[str, Any] = field(default_factory=dict)


def resolve_api_key(
    explicit: Optional[str] = None,
    env_var: str = "OPENROUTER_API_KEY",
    key_file_paths: Optional[list[Path]] = None,
) -> Optional[str]:
    """Return an API key from the first available source.

    Resolution order:
      1. *explicit* argument (passed directly by caller)
      2. Environment variable *env_var*
      3. First readable file in *key_file_paths* whose content is non-empty

    Returns ``None`` if no key can be found.
    """
    if explicit:
        return explicit

    from_env = os.environ.get(env_var)
    if from_env:
        return from_env.strip()

    for path in key_file_paths or []:
        try:
            text = path.read_text().strip()
            if text:
                return text
        except OSError:
            continue

    return None


def find_project_root(start: Optional[Path] = None) -> Optional[Path]:
    """Walk up from *start* (default CWD) looking for ``pyproject.toml``.

    Returns the directory containing the marker file, or ``None``.
    """
    current = (start or Path.cwd()).resolve()
    for directory in [current, *current.parents]:
        if (directory / "pyproject.toml").is_file():
            return directory
    return None


def load_config(
    provider: str = "openrouter",
    model: Optional[str] = None,
    api_key: Optional[str] = None,
    **overrides: Any,
) -> LLMConfig:
    """Build an :class:`LLMConfig` with sensible defaults.

    For the ``openrouter`` provider the API key is resolved via
    :func:`resolve_api_key` (env var → project-root key file).
    """
    root = find_project_root()
    key_file_paths = [root / "apikey-openrouter.txt"] if root else []

    resolved_key = api_key
    if provider == "openrouter" and not resolved_key:
        resolved_key = resolve_api_key(
            explicit=None,
            env_var="OPENROUTER_API_KEY",
            key_file_paths=key_file_paths,
        )

    defaults: Dict[str, Any] = {
        "provider": provider,
        "model": model or "anthropic/claude-sonnet-4",
        "api_key": resolved_key,
    }
    defaults.update(overrides)
    return LLMConfig(**defaults)
