"""Config + credential resolution.

Two stores, resolved in order (env wins, then project, then user):
  - env: ACSETRA_API_BASE / ACSETRA_TOKEN / ACSETRA_WORKSPACE
  - project: ./.runner/config.json  (api_base, workspace, default_scope, dev_port)
  - user:    ~/.config/acsetra/credentials  (api_base, token, workspace, user_sub)

The token only ever lives in the user credential file (chmod 600), never in the
project config (which is safe to commit). signin writes the user store; `--api`
and workspace switches update the project store.
"""
import json
import os
import stat
from pathlib import Path

DEFAULT_API_BASE = "https://pen.acsetra.com"

USER_DIR = Path(os.environ.get("ACSETRA_HOME") or (Path.home() / ".config" / "acsetra"))
CRED_PATH = USER_DIR / "credentials"
PROJECT_DIR = Path(".runner")
PROJECT_CFG = PROJECT_DIR / "config.json"


def _read_json(path):
    try:
        return json.loads(Path(path).read_text())
    except (FileNotFoundError, ValueError, OSError):
        return {}


def load_user():
    return _read_json(CRED_PATH)


def load_project():
    return _read_json(PROJECT_CFG)


def save_user(data):
    USER_DIR.mkdir(parents=True, exist_ok=True)
    CRED_PATH.write_text(json.dumps(data, indent=2))
    try:
        CRED_PATH.chmod(stat.S_IRUSR | stat.S_IWUSR)   # 0600 — secrets are user-only
    except OSError:
        pass


def save_project(data):
    PROJECT_DIR.mkdir(parents=True, exist_ok=True)
    PROJECT_CFG.write_text(json.dumps(data, indent=2))


def api_base():
    return (os.environ.get("ACSETRA_API_BASE")
            or load_project().get("api_base")
            or load_user().get("api_base")
            or DEFAULT_API_BASE).rstrip("/")


def token():
    return os.environ.get("ACSETRA_TOKEN") or load_user().get("token")


def workspace():
    return (os.environ.get("ACSETRA_WORKSPACE")
            or load_project().get("workspace")
            or load_user().get("workspace"))


def default_scope():
    return os.environ.get("ACSETRA_SCOPE") or load_project().get("default_scope")


def set_project(**kw):
    cfg = load_project()
    cfg.update({k: v for k, v in kw.items() if v is not None})
    save_project(cfg)
    return cfg
