from __future__ import annotations

from typing import Any, Dict, Optional

import requests


class ShopifyAdminGraphQLClient:
    """Small Shopify Admin GraphQL client for registry/bootstrap jobs."""

    def __init__(
        self,
        *,
        shop_domain: str,
        admin_access_token: Optional[str] = None,
        client_id: Optional[str] = None,
        client_secret: Optional[str] = None,
        api_version: str = "2026-04",
        timeout_s: int = 60,
    ) -> None:
        domain = str(shop_domain or "").strip().replace("https://", "").replace("http://", "").strip("/")
        if not domain:
            raise ValueError("SHOPIFY_SHOP_DOMAIN is required")
        self.shop_domain = domain
        self.timeout_s = timeout_s
        self.admin_access_token = admin_access_token or self._fetch_client_credentials_token(
            client_id=client_id,
            client_secret=client_secret,
        )
        self.api_version = api_version or "2026-04"
        self.endpoint = f"https://{self.shop_domain}/admin/api/{self.api_version}/graphql.json"

    def graphql(self, query: str, variables: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        response = requests.post(
            self.endpoint,
            headers={
                "Content-Type": "application/json",
                "X-Shopify-Access-Token": self.admin_access_token,
            },
            json={"query": query, "variables": variables or {}},
            timeout=self.timeout_s,
        )
        response.raise_for_status()
        payload = response.json()
        if payload.get("errors"):
            raise RuntimeError(f"Shopify GraphQL errors: {payload['errors']}")
        return payload.get("data") or {}

    def _fetch_client_credentials_token(
        self,
        *,
        client_id: Optional[str],
        client_secret: Optional[str],
    ) -> str:
        if not client_id or not client_secret:
            raise ValueError("SHOPIFY_ADMIN_ACCESS_TOKEN or SHOPIFY_CLIENT_ID/SHOPIFY_CLIENT_SECRET is required")
        response = requests.post(
            f"https://{self.shop_domain}/admin/oauth/access_token",
            headers={"Content-Type": "application/x-www-form-urlencoded"},
            data={
                "grant_type": "client_credentials",
                "client_id": client_id,
                "client_secret": client_secret,
            },
            timeout=self.timeout_s,
        )
        response.raise_for_status()
        payload = response.json()
        token = payload.get("access_token")
        if not token:
            raise RuntimeError(f"Shopify token response did not include access_token: {payload}")
        return str(token)
