"""
Minimal Microquery API client.

Usage:
    from client import MicroqueryClient
    mq = MicroqueryClient(api_key="your_token")
    rows = mq.query("nvd", "SELECT cve_id FROM cve LIMIT 5")
"""

import json
import sys
import time
import urllib.error
import urllib.parse
import urllib.request
from typing import Any

API_BASE = "https://microquery.dev"


class QueryError(Exception):
    pass


class MicroqueryClient:
    def __init__(self, api_key: str, base_url: str = API_BASE):
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")
        self.total_cost_micro_usdc = 0
        self.total_bytes_scanned = 0

    def query(self, database: str, sql: str, *, verbose: bool = False) -> list[dict]:
        """Run SQL against a database. Returns list of result rows."""
        url = f"{self.base_url}/query?database={urllib.parse.quote(database)}"
        req = urllib.request.Request(
            url,
            data=sql.encode(),
            method="POST",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "text/plain",
            },
        )
        try:
            with urllib.request.urlopen(req, timeout=120) as resp:
                cost = int(resp.headers.get("X-Microquery-Cost-MicroUSDC", 0))
                scanned = int(resp.headers.get("X-Microquery-Bytes-Scanned", 0))
                self.total_cost_micro_usdc += cost
                self.total_bytes_scanned += scanned
                if verbose:
                    print(
                        f"  [{database}] scanned={scanned/1e6:.2f}MB "
                        f"cost=${cost/1e6:.6f}",
                        file=sys.stderr,
                    )
                raw = resp.read().decode()
        except urllib.error.HTTPError as e:
            body = e.read().decode()
            raise QueryError(f"HTTP {e.code}: {body}") from e

        rows = []
        for line in raw.splitlines():
            line = line.strip()
            if line:
                rows.append(json.loads(line))
        return rows

    def cost_summary(self) -> str:
        mb = self.total_bytes_scanned / 1e6
        usd = self.total_cost_micro_usdc / 1e6
        return f"Total: {mb:.1f} MB scanned, ${usd:.6f} USDC"
