"""Load the Claude Code OAuth access token from ~/.claude/.credentials.json."""

import json
import os
import sys
import time
from pathlib import Path


_DEFAULT_CREDENTIALS_PATH = "~/.claude/.credentials.json"


def load_claude_oauth_token(
    credentials_path: str = "",
    refresh_if_expired: bool = True,
) -> str:
    """Return the Claude Code OAuth access token.

    Reads ``~/.claude/.credentials.json`` (or the path you supply),
    extracts ``claudeAiOauth.accessToken`` and checks expiry.

    If ``refresh_if_expired`` is True and the token appears expired a
    best-effort refresh via the Anthropic OAuth token endpoint is attempted
    using the stored ``refreshToken``.  The refresh may silently fail — in
    that case a warning is written to *stderr* and the (possibly expired)
    access token is returned anyway.  The ``claude`` CLI normally refreshes
    the token in the background; if you keep Claude Code open the token
    will usually already be fresh.

    Args:
        credentials_path: Absolute or ``~``-relative path to the credentials
            file.  Defaults to ``~/.claude/.credentials.json``.
        refresh_if_expired: Attempt a token refresh when the stored
            ``expiresAt`` (milliseconds epoch) is in the past.  Set to
            False to skip the network call entirely.

    Returns:
        The raw access token string (``sk-ant-oat-...``).  Never printed to
        stdout.

    Raises:
        FileNotFoundError: If the credentials file does not exist.
        KeyError: If the expected keys are missing from the JSON.
        json.JSONDecodeError: If the file is not valid JSON.
    """
    path = Path(credentials_path or _DEFAULT_CREDENTIALS_PATH).expanduser()
    raw = path.read_text(encoding="utf-8")
    data = json.loads(raw)

    oauth = data["claudeAiOauth"]
    access_token: str = oauth["accessToken"]
    expires_at_ms: int = oauth.get("expiresAt", 0)
    refresh_token: str = oauth.get("refreshToken", "")

    now_ms = int(time.time() * 1000)
    is_expired = expires_at_ms > 0 and expires_at_ms <= now_ms

    if is_expired and refresh_if_expired and refresh_token:
        new_token = _try_refresh(refresh_token)
        if new_token:
            return new_token
        print(
            "warning: Claude OAuth token may be expired; refresh failed. "
            "Returning current token anyway.",
            file=sys.stderr,
        )

    return access_token


def _try_refresh(refresh_token: str) -> str:
    """Attempt to refresh the OAuth token.  Returns empty string on failure.

    The Anthropic OAuth refresh endpoint is not publicly documented.
    This is a best-effort attempt using standard OAuth 2.0 conventions
    (grant_type=refresh_token).  It may not work if Anthropic changes
    their token endpoint or requires additional client credentials.
    """
    try:
        import httpx  # type: ignore

        resp = httpx.post(
            "https://auth.anthropic.com/oauth/token",
            data={
                "grant_type": "refresh_token",
                "refresh_token": refresh_token,
            },
            headers={"content-type": "application/x-www-form-urlencoded"},
            timeout=10.0,
        )
        if resp.status_code == 200:
            body = resp.json()
            new_token: str = body.get("access_token", "")
            if new_token:
                return new_token
    except Exception as exc:  # noqa: BLE001
        print(f"warning: token refresh attempt failed: {exc}", file=sys.stderr)

    return ""
