"""Specter local configuration management.

Manages ``~/.specter/`` directory with:
- ``auth.json`` — authentication token from ``specter login``
- ``remote.json`` — active GPU session config (host, port, user, session_id)
- ``ssh/`` — ControlMaster socket directory
- ``envs/`` — venv-like environment directories
"""

from __future__ import annotations

import json
import logging
import os
from pathlib import Path
from typing import Any

log = logging.getLogger(__name__)


def specter_dir() -> Path:
    """Root configuration directory.

    Defaults to ``~/.specter``, overridable via ``SPECTER_HOME`` env var.
    """
    return Path(os.environ.get("SPECTER_HOME", Path.home() / ".specter"))


def auth_file() -> Path:
    """Path to auth.json."""
    return specter_dir() / "auth.json"


def remote_file() -> Path:
    """Path to remote.json."""
    return specter_dir() / "remote.json"


def envs_dir() -> Path:
    """Path to envs/ directory."""
    return specter_dir() / "envs"


def ensure_specter_dir() -> Path:
    """Create ~/.specter/ directory tree if it doesn't exist."""
    d = specter_dir()
    d.mkdir(parents=True, exist_ok=True)
    (d / "ssh").mkdir(exist_ok=True)
    envs_dir().mkdir(exist_ok=True)
    return d


def load_auth() -> dict[str, Any]:
    """Load auth token from ~/.specter/auth.json.

    Returns
    -------
    Dict with at least ``token`` key, or empty dict if not logged in.
    """
    af = auth_file()
    if not af.is_file():
        return {}
    try:
        return json.loads(af.read_text())
    except (json.JSONDecodeError, OSError) as e:
        log.warning("Failed to read auth config: %s", e)
        return {}


def save_auth(token: str, **extra: Any) -> None:
    """Save auth token to ~/.specter/auth.json."""
    ensure_specter_dir()
    af = auth_file()
    data = {"token": token, **extra}
    af.write_text(json.dumps(data, indent=2) + "\n")
    af.chmod(0o600)  # Restrict access to owner only.
    log.debug("Auth token saved to %s", af)


def clear_auth() -> None:
    """Remove auth token."""
    af = auth_file()
    if af.is_file():
        af.unlink()
        log.debug("Auth token removed")


def get_token() -> str | None:
    """Get the current auth token, or None if not logged in."""
    auth = load_auth()
    return auth.get("token")


def load_remote_config() -> dict[str, Any]:
    """Load remote GPU session config from ~/.specter/remote.json.

    Returns
    -------
    Dict with keys: host, user, ssh_port, session_id, workspace, etc.
    Empty dict if no active session.
    """
    rf = remote_file()
    if not rf.is_file():
        return {}
    try:
        return json.loads(rf.read_text())
    except (json.JSONDecodeError, OSError) as e:
        log.warning("Failed to read remote config: %s", e)
        return {}


def save_remote_config(
    *,
    host: str,
    user: str,
    ssh_port: int = 22,
    session_id: str,
    gpu_type: str,
    workspace: str = "~/.specter/workspace",
    **extra: Any,
) -> None:
    """Save remote GPU session config."""
    ensure_specter_dir()
    rf = remote_file()
    data = {
        "host": host,
        "user": user,
        "ssh_port": ssh_port,
        "session_id": session_id,
        "gpu_type": gpu_type,
        "workspace": workspace,
        **extra,
    }
    rf.write_text(json.dumps(data, indent=2) + "\n")
    log.debug("Remote config saved to %s", rf)


def clear_remote_config() -> None:
    """Remove remote session config."""
    rf = remote_file()
    if rf.is_file():
        rf.unlink()
        log.debug("Remote config removed")


def has_active_session() -> bool:
    """Check if there's an active GPU session configured."""
    config = load_remote_config()
    return bool(config.get("host") and config.get("session_id"))
