"""Small shared helpers. Anything bigger belongs in its own module."""

from __future__ import annotations

import os
import secrets
import subprocess
from datetime import datetime, timezone
from pathlib import Path

from dotenv import load_dotenv

load_dotenv()


def operator_env(account: str | None = None) -> dict[str, str]:
    """The engineer's own environment, as their shell would hand it over.

    Agents and quality blocks are meant to see exactly what the operator sees:
    their PATH, their toolchains, their globally installed packages. Copying
    os.environ gets almost all the way there — but ADWs launch under `uv run`,
    which prepends its ephemeral venv's bin to PATH and sets VIRTUAL_ENV. That
    venv holds the ADW's OWN dependencies (pydantic, pyyaml), not the
    operator's, so anything a subprocess resolves through it — `python3`,
    `pip`, every globally pip-installed CLI — silently becomes the wrong one.

    Stripping the venv restores parity: `python3` in an agent's bash is the
    same `python3` the engineer gets in their terminal. The ADW's own imports
    are unaffected; this env is only ever handed to child processes.
    """
    env = os.environ.copy()
    venv = env.pop("VIRTUAL_ENV", "")
    if venv:
        venv_bin = str(Path(venv) / "bin")
        parts = [p for p in env.get("PATH", "").split(os.pathsep) if p and p != venv_bin]
        env["PATH"] = os.pathsep.join(parts)
    if account:
        from .accounts import materialize_account
        account_dir = materialize_account(account)
        env["PI_CODING_AGENT_DIR"] = str(account_dir)
        env["FACTORY_PI_ACCOUNT_DIR"] = str(account_dir)
    return env


def cleanup_operator_env(env: dict[str, str]) -> None:
    account_dir = env.get("FACTORY_PI_ACCOUNT_DIR")
    if account_dir:
        from .accounts import cleanup_account
        cleanup_account(Path(account_dir))


def new_id(length: int = 8) -> str:
    return secrets.token_hex(length // 2)


def now_iso() -> str:
    return datetime.now(timezone.utc).isoformat(timespec="milliseconds")


def ensure_dir(path: str | Path) -> Path:
    p = Path(path)
    p.mkdir(parents=True, exist_ok=True)
    return p


def resolve_prompt(arg: str) -> str:
    """CLI prompt arg: a file path resolves to its contents, else inline text."""
    try:
        p = Path(arg)
        if p.is_file():
            return p.read_text()
    except OSError:
        pass
    return arg


def classify_slug_hint(arg: str | None) -> tuple[str, bool] | None:
    """Classify a CLI slug hint as an existing path or inline text."""
    if arg is None:
        return None
    raw = arg.strip()
    if not raw:
        return None
    try:
        if Path(raw).is_file():
            return raw, True
    except OSError:
        pass
    return raw, False


def engineer_name() -> str:
    name = os.environ.get("ENGINEER_NAME", "").strip()
    if name:
        return name
    try:
        out = subprocess.run(["git", "config", "user.name"],
                             capture_output=True, text=True, timeout=5)
        if out.returncode == 0 and out.stdout.strip():
            return out.stdout.strip()
    except OSError:
        pass
    return os.environ.get("USER", "engineer")
