import json
import os
import urllib.request
import urllib.error
from pathlib import Path


USAGE_URL = "https://api.anthropic.com/api/oauth/usage"


class FetchError(Exception):
    """Raised for recoverable API errors (network issues, non-401 HTTP errors)."""


LIMIT_NAMES = {
    "five_hour": "5-Hour Session",
    "seven_day": "7-Day Weekly",
    "seven_day_oauth_apps": "7-Day OAuth Apps",
    "seven_day_opus": "7-Day Opus",
    "seven_day_sonnet": "7-Day Sonnet",
    "seven_day_haiku": "7-Day Haiku",
}


def get_extra_usage_enabled() -> bool | None:
    """Return whether extra usage is enabled, or None if unknown."""
    config_path = Path.home() / ".claude.json"
    try:
        with open(config_path) as f:
            data = json.load(f)
        return data["oauthAccount"]["hasExtraUsageEnabled"]
    except (FileNotFoundError, KeyError, json.JSONDecodeError):
        return None


def get_access_token() -> str:
    """Return the OAuth access token or raise SystemExit with a helpful message."""
    token = os.environ.get("CLAUDE_CODE_OAUTH_TOKEN")
    if token:
        return token

    creds_path = Path.home() / ".claude" / ".credentials.json"
    if not creds_path.exists():
        raise SystemExit(
            "Error: No credentials found.\n"
            "Set CLAUDE_CODE_OAUTH_TOKEN or log in with Claude Code first."
        )

    with open(creds_path) as f:
        creds = json.load(f)

    try:
        return creds["claudeAiOauth"]["accessToken"]
    except KeyError:
        raise SystemExit(
            "Error: No OAuth token found in ~/.claude/.credentials.json.\n"
            "Log in with Claude Code first."
        )


def fetch_usage(token: str) -> list[dict]:
    """Fetch usage data from the Claude API. Returns a list of limit dicts."""
    req = urllib.request.Request(USAGE_URL)
    req.add_header("Authorization", f"Bearer {token}")
    req.add_header("anthropic-beta", "oauth-2025-04-20")
    req.add_header("Content-Type", "application/json")

    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read())
    except urllib.error.HTTPError as e:
        if e.code == 401:
            raise SystemExit(
                "Error: Authentication failed. Your token may be expired.\n"
                "Re-authenticate with Claude Code."
            )
        raise FetchError(f"API returned HTTP {e.code}")
    except urllib.error.URLError as e:
        raise FetchError(f"Could not reach API: {e.reason}")

    limits = []
    for key, value in data.items():
        if value is None:
            continue
        if not isinstance(value, dict) or "utilization" not in value:
            continue
        if value["utilization"] is None:
            continue

        name = LIMIT_NAMES.get(key, key.replace("_", " ").title())
        limits.append({
            "name": name,
            "utilization": float(value["utilization"]),
            "resets_at": value.get("resets_at"),
        })

    return limits
