"""IPSee Python SDK v1 — standard library only, Python 3.9+."""
from __future__ import annotations

import json
from urllib.error import HTTPError
from urllib.parse import quote, urlencode
from urllib.request import Request, urlopen


class SoipError(RuntimeError):
    def __init__(self, message: str, status: int, body: dict):
        super().__init__(message)
        self.status = status
        self.body = body


class SoipClient:
    def __init__(self, api_key: str, base_url: str = "https://your-domain.example/api/v1", timeout: float = 15):
        if not api_key:
            raise ValueError("api_key is required")
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")
        self.timeout = timeout

    def _request(self, path: str, payload: dict | None = None) -> dict:
        data = json.dumps(payload).encode() if payload is not None else None
        request = Request(self.base_url + path, data=data, headers={"x-api-key": self.api_key, "content-type": "application/json"})
        try:
            with urlopen(request, timeout=self.timeout) as response:
                return json.load(response)
        except HTTPError as error:
            try:
                body = json.load(error)
            except Exception:
                body = {}
            raise SoipError(str(body.get("message") or error.reason), error.code, body) from error

    def lookup(self, ip: str, lang: str = "en") -> dict:
        return self._request(f"/ip/{quote(ip, safe='')}?{urlencode({'lang': lang})}")

    def batch(self, ips: list[str], lang: str = "en") -> dict:
        return self._request("/ip/batch", {"ips": ips, "lang": lang})

    def account(self) -> dict:
        return self._request("/account")
