"""Async HTTP client for PocketBase REST API.

All PocketBase I/O goes through this module. Repositories import functions
from here — they do not construct httpx clients directly.
"""
from __future__ import annotations

import httpx
import structlog

from config import settings

log = structlog.get_logger()

# ── Internal helpers ──────────────────────────────────────────────────────────

def _client() -> httpx.AsyncClient:
    return httpx.AsyncClient(base_url=settings.pocketbase_url, timeout=10.0)


# ── User operations ───────────────────────────────────────────────────────────

async def get_user_by_token(token: str) -> dict:
    """Validate a PocketBase auth token and return the user record.

    Raises httpx.HTTPStatusError if the token is invalid or expired.
    """
    async with _client() as client:
        resp = await client.get(
            '/api/collections/users/auth-refresh',
            headers={'Authorization': f'Bearer {token}'},
        )
        resp.raise_for_status()
        body = resp.json()
        record = body['record']
        record['token'] = body['token']  # refreshed token
        return record


async def get_user_by_id(user_id: str, admin_token: str) -> dict:
    """Fetch a user record by ID using an admin token."""
    async with _client() as client:
        resp = await client.get(
            f'/api/collections/users/records/{user_id}',
            headers={'Authorization': f'Bearer {admin_token}'},
        )
        resp.raise_for_status()
        return resp.json()


# ── Conversion operations ─────────────────────────────────────────────────────

async def create_conversion(user_id: str, file_hash: str, admin_token: str) -> str:
    """Create a conversion record. Triggers the credit-deduction hook atomically.

    Returns the new record ID. Raises httpx.HTTPStatusError on failure,
    including INSUFFICIENT_CREDITS from the hook.
    """
    async with _client() as client:
        resp = await client.post(
            '/api/collections/conversions/records',
            json={'user': user_id, 'file_hash': file_hash, 'status': 'pending'},
            headers={'Authorization': f'Bearer {admin_token}'},
        )
        resp.raise_for_status()
        return resp.json()['id']


async def update_conversion_status(record_id: str, status: str, admin_token: str) -> None:
    """Update conversion status to 'complete' or 'failed'."""
    async with _client() as client:
        resp = await client.patch(
            f'/api/collections/conversions/records/{record_id}',
            json={'status': status},
            headers={'Authorization': f'Bearer {admin_token}'},
        )
        resp.raise_for_status()


async def update_conversion_download_url(record_id: str, url: str, admin_token: str) -> None:
    """Store the MinIO presigned download URL on the conversion record."""
    async with _client() as client:
        resp = await client.patch(
            f'/api/collections/conversions/records/{record_id}',
            json={'status': 'complete', 'download_url': url},
            headers={'Authorization': f'Bearer {admin_token}'},
        )
        resp.raise_for_status()


# ── Purchase operations ───────────────────────────────────────────────────────

async def create_purchase(user_id: str, credits: int, stripe_id: str, admin_token: str) -> str:
    """Create a purchase record. Triggers the credit top-up hook atomically."""
    async with _client() as client:
        resp = await client.post(
            '/api/collections/purchases/records',
            json={'user': user_id, 'credits': credits, 'stripe_id': stripe_id},
            headers={'Authorization': f'Bearer {admin_token}'},
        )
        resp.raise_for_status()
        return resp.json()['id']
