"""
Public configuration defaults for CHNB.

Keep local paths, project IDs, API keys, and model snapshot choices out of the
experiment code. Users can override secrets and local filesystem locations via
environment variables; experiment-specific protocol choices stay in the runner
that owns them.
"""
from __future__ import annotations

import os
import shlex
from pathlib import Path


# Environment-file lookup. See .env.example for the public template.
ENV_FILE_ENV = 'CHNB_ENV_FILE'
ENV_OVERRIDE_ENV = 'CHNB_ENV_OVERRIDE'
USER_CONFIG_DIR = Path.home() / '.config' / 'chnb'
USER_ENV_FILE = USER_CONFIG_DIR / '.env'


# Path override env vars.
PROJECT_ROOT_ENV = 'CHNB_PROJECT_ROOT'
DATA_ROOT_ENV = 'CHNB_DATA_ROOT'
OUTPUT_ROOT_ENV = 'CHNB_OUTPUT_ROOT'
BENCHMARK_ENV = 'CHNB_BENCHMARK'
VIDEO_DIR_ENV = 'CHNB_VIDEO_DIR'
SUBTITLES_DIR_ENV = 'CHNB_SUBTITLES_DIR'
SHOTS_DIR_ENV = 'CHNB_SHOTS_DIR'
GCS_BUCKET_ENV = 'CHNB_GCS_BUCKET'
MOVIE_METADATA_ENV = 'CHNB_MOVIE_METADATA'
FRAMES_DIR_ENV = 'CHNB_FRAMES_DIR'
CLIP_EMBEDDINGS_DIR_ENV = 'CHNB_CLIP_EMBEDDINGS_DIR'
CLIPS_DIR_ENV = 'CHNB_CLIPS_DIR'
CAPTIONS_DIR_ENV = 'CHNB_CAPTIONS_DIR'
RESULTS_DIR_ENV = 'CHNB_RESULTS_DIR'
WSH_DIR_ENV = 'CHNB_WSH_DIR'


# Service env vars. Values belong in the user's shell, .env, or secret manager.
GOOGLE_CLOUD_PROJECT_ENV = 'GOOGLE_CLOUD_PROJECT'
OPENAI_API_KEY_ENV = 'OPENAI_API_KEY'
ANTHROPIC_API_KEY_ENV = 'ANTHROPIC_API_KEY'
LETTA_BASE_URL_ENV = 'LETTA_BASE_URL'
LETTA_API_KEY_ENV = 'LETTA_API_KEY'
LETTA_LOCAL_LLM_URL_ENV = 'LETTA_LOCAL_LLM_URL'
LETTA_LOCAL_LLM_API_KEY_ENV = 'LETTA_LOCAL_LLM_API_KEY'


DEFAULT_VERTEX_LOCATION = 'global'
DEFAULT_SYSTEM_INSTRUCTION = 'You are a helpful assistant.'


DEFAULT_MODELS: dict[str, str] = {
    'gemini': 'gemini-3-flash-preview',
    'gpt': 'gpt-5-mini',
    'claude': 'claude-haiku-4-5',
    'qwen3vl': 'Qwen/Qwen3-VL-8B-Instruct',
    'qwen3': 'Qwen/Qwen3-8B',
    'glm4v': 'THUDM/GLM-4.1V-9B-Thinking',
    'glm4': 'THUDM/glm-4-9b-chat-hf',
    'llava_next_video': 'llava-hf/LLaVA-NeXT-Video-7B-DPO-hf',
    'hourllava': 'jylins/hourllava-qwen2-7b-s3',
    'vamba': 'TIGER-Lab/Vamba-Qwen2-VL-7B',
    'videochat': 'OpenGVLab/VideoChat-Flash-Qwen2_5-7B-1M_res224',
}


DEFAULT_LETTA_BASE_URL = 'http://localhost:8283'
DEFAULT_LETTA_LOCAL_LLM_URL = 'http://localhost:8001/v1'
DEFAULT_LETTA_LOCAL_LLM_API_KEY = 'dummy'


_PUBLIC_ENV_LOADED = False


def _parse_env_line(line: str) -> tuple[str, str] | None:
    """Parse a simple KEY=VALUE line from a public .env file."""
    line = line.strip()
    if not line or line.startswith('#'):
        return None
    if line.startswith('export '):
        line = line[len('export '):].strip()
    if '=' not in line:
        return None
    key, raw_value = line.split('=', 1)
    key = key.strip()
    if not key:
        return None
    value = raw_value.strip()
    if value:
        try:
            parts = shlex.split(value, comments=False, posix=True)
        except ValueError:
            parts = []
        if len(parts) == 1:
            value = parts[0]
        else:
            value = value.strip('"').strip("'")
    return key, value


def _load_env_file(path: Path, *, override: bool, locked: set[str]) -> bool:
    if not path.exists() or not path.is_file():
        return False
    for line in path.read_text(encoding='utf-8', errors='ignore').splitlines():
        parsed = _parse_env_line(line)
        if parsed is None:
            continue
        key, value = parsed
        if key in locked:
            continue
        if override or key not in os.environ:
            os.environ[key] = value
        locked.add(key)
    return True


def load_public_env(default_project_root: Path | None = None) -> list[Path]:
    """
    Load CHNB .env files without requiring python-dotenv.

    This runs before path constants are resolved, so path overrides such as
    CHNB_DATA_ROOT and CHNB_FRAMES_DIR work from .env as well as from the shell.
    Lookup priority matches util.secrets: CHNB_ENV_FILE, project .env, then
    ~/.config/chnb/.env.
    """
    global _PUBLIC_ENV_LOADED
    if _PUBLIC_ENV_LOADED:
        return []
    _PUBLIC_ENV_LOADED = True

    root = default_project_root or Path(__file__).resolve().parents[1]
    override = os.environ.get(ENV_OVERRIDE_ENV, '1').lower() not in ('0', 'false', 'no')

    paths: list[Path] = []
    explicit = os.environ.get(ENV_FILE_ENV, '').strip()
    if explicit:
        paths.append(Path(explicit).expanduser())
    paths.append(Path(root).expanduser() / '.env')
    paths.append(USER_ENV_FILE)

    loaded: list[Path] = []
    locked: set[str] = set()
    for path in paths:
        if _load_env_file(path, override=override, locked=locked):
            loaded.append(path)
    return loaded
