"""Cloudflare API v4 client.

Read operations use the config file token (or env var fallback).
Write operations use a PIN-decrypted token that never leaves this module.
"""

import os

import httpx

from clawdflare.lib import vault

BASE_URL = "https://api.cloudflare.com/client/v4"


def _get_read_token() -> str:
    """Get read-only Cloudflare API token. Config file first, env var fallback."""
    token = vault.get_read_token()
    if token:
        return token

    token = os.environ.get("CLOUDFLARE_API_TOKEN") or os.environ.get("CF_API_TOKEN")
    if token:
        return token

    raise RuntimeError(
        "No read token found. Run `clawdflare setup` or set CLOUDFLARE_API_TOKEN."
    )


def _read_headers() -> dict:
    return {
        "Authorization": f"Bearer {_get_read_token()}",
        "Content-Type": "application/json",
    }


def _write_headers(token: str) -> dict:
    """Build headers with a write token. Token must not be stored or logged."""
    return {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }


# ---------------------------------------------------------------------------
# Read operations (config/env var token)
# ---------------------------------------------------------------------------

async def get(path: str, params: dict | None = None) -> dict:
    async with httpx.AsyncClient(base_url=BASE_URL, headers=_read_headers(), timeout=30) as c:
        r = await c.get(path, params=params)
        r.raise_for_status()
        return r.json()


# ---------------------------------------------------------------------------
# Write operations (PIN-decrypted token, scoped to single call)
# ---------------------------------------------------------------------------

async def write_patch(path: str, data: dict, token: str) -> dict:
    """PATCH with a write token. Token is used once and not stored."""
    headers = _write_headers(token)
    async with httpx.AsyncClient(base_url=BASE_URL, headers=headers, timeout=30) as c:
        r = await c.patch(path, json=data)
        r.raise_for_status()
        return r.json()


async def write_post(path: str, data: dict, token: str) -> dict:
    """POST with a write token. Token is used once and not stored."""
    headers = _write_headers(token)
    async with httpx.AsyncClient(base_url=BASE_URL, headers=headers, timeout=30) as c:
        r = await c.post(path, json=data)
        r.raise_for_status()
        return r.json()


async def write_put(path: str, data: dict, token: str) -> dict:
    """PUT with a write token. Token is used once and not stored."""
    headers = _write_headers(token)
    async with httpx.AsyncClient(base_url=BASE_URL, headers=headers, timeout=30) as c:
        r = await c.put(path, json=data)
        r.raise_for_status()
        return r.json()


async def write_delete(path: str, token: str) -> dict:
    """DELETE with a write token. Token is used once and not stored."""
    headers = _write_headers(token)
    async with httpx.AsyncClient(base_url=BASE_URL, headers=headers, timeout=30) as c:
        r = await c.delete(path)
        r.raise_for_status()
        return r.json()
