"""Config loading — TOML topology + .env secrets."""
from __future__ import annotations

import os
import tomllib
from dataclasses import dataclass, field
from pathlib import Path

from dotenv import load_dotenv

# Device adaptation: everything the brain persists lives beside the rest of
# the koi's state, not in the install directory (which npm may replace).
ROOT = Path.home() / ".skykoi" / "koi-brain"


@dataclass
class Config:
    base_url: str = "https://api.groq.com/openai/v1"
    api_key: str = ""
    primary_model: str = "qwen/qwen3.6-27b"
    fallback_models: list[str] = field(
        default_factory=lambda: ["openai/gpt-oss-120b", "openai/gpt-oss-20b"]
    )
    no_think: bool = True

    browser_engine: str = "auto"
    browser_executable_path: str = ""
    browser_cdp_url: str = ""
    browser_headless: bool = False
    browser_shared_window: bool = True
    browser_profile_dir: str = "data/browser-profile"
    browser_flash_mode: bool = True
    browser_use_vision: str | bool = "auto"
    browser_max_parallel: int = 3

    # "auto" on a device: safe ops run free, the denylist blocks the dangerous
    # ones, and nothing waits on a terminal prompt no service can answer.
    # KOI_BRAIN_POLICY overrides (the exec-approvals bridge is future work).
    policy_mode: str = "auto"
    shell_timeout: int = 90

    max_worker_iterations: int = 12
    max_plan_steps: int = 8

    cognition_verify: bool = True
    # "auto": the router classifies each task's depth (fast/full/loop).
    # A fixed value forces that depth on every task; "fast" also skips the
    # post-synthesis verify pass, since verify only runs on full/loop.
    cognition_mode: str = "auto"

    memory_db: Path = ROOT / "data" / "memory.db"
    recall_limit: int = 5


def load_config() -> Config:
    load_dotenv(ROOT / ".env")
    cfg = Config()
    path = ROOT / "config.toml"
    if path.exists():
        raw = tomllib.loads(path.read_text(encoding="utf-8"))
        prov = raw.get("provider", {})
        cfg.base_url = prov.get("base_url", cfg.base_url)
        key_env = prov.get("api_key_env", "GROQ_API_KEY")
        cfg.api_key = os.environ.get(key_env, "")

        models = raw.get("models", {})
        cfg.primary_model = models.get("primary", cfg.primary_model)
        cfg.fallback_models = models.get("fallbacks", [])
        cfg.no_think = models.get("no_think", cfg.no_think)

        br = raw.get("browser", {})
        cfg.browser_engine = br.get("engine", cfg.browser_engine)
        cfg.browser_executable_path = br.get("executable_path", cfg.browser_executable_path)
        cfg.browser_cdp_url = br.get("cdp_url", cfg.browser_cdp_url)
        cfg.browser_headless = br.get("headless", cfg.browser_headless)
        cfg.browser_shared_window = br.get("shared_window", cfg.browser_shared_window)
        cfg.browser_profile_dir = br.get("profile_dir", cfg.browser_profile_dir)
        cfg.browser_flash_mode = br.get("flash_mode", cfg.browser_flash_mode)
        cfg.browser_use_vision = br.get("use_vision", cfg.browser_use_vision)
        cfg.browser_max_parallel = br.get("max_parallel", cfg.browser_max_parallel)

        pol = raw.get("policy", {})
        cfg.policy_mode = pol.get("mode", cfg.policy_mode)
        cfg.shell_timeout = pol.get("shell_timeout", cfg.shell_timeout)

        orch = raw.get("orchestrator", {})
        cfg.max_worker_iterations = orch.get("max_worker_iterations", cfg.max_worker_iterations)
        cfg.max_plan_steps = orch.get("max_plan_steps", cfg.max_plan_steps)

        cogn = raw.get("cognition", {})
        cfg.cognition_verify = cogn.get("verify", cfg.cognition_verify)
        cfg.cognition_mode = cogn.get("mode", cfg.cognition_mode)

        mem = raw.get("memory", {})
        if "db_path" in mem:
            cfg.memory_db = ROOT / mem["db_path"]
        cfg.recall_limit = mem.get("recall_limit", cfg.recall_limit)
    else:
        cfg.api_key = os.environ.get("GROQ_API_KEY", "")
    if os.environ.get("KOI_BRAIN_POLICY") in ("supervised", "auto", "yolo"):
        cfg.policy_mode = os.environ["KOI_BRAIN_POLICY"]
    if os.environ.get("KOI_BRAIN_MODEL"):
        cfg.primary_model = os.environ["KOI_BRAIN_MODEL"]
    return cfg
