from __future__ import annotations

from typing import Dict, Optional

VARIANT_SKU_PAGE_QUERY = """
query variantSkuPage($cursor: String) {
  productVariants(first: 250, after: $cursor) {
    nodes {
      sku
      product { id }
    }
    pageInfo { hasNextPage endCursor }
  }
}
"""

VARIANT_SKU_LOOKUP_QUERY = """
query variantSkuLookup($query: String!, $cursor: String) {
  productVariants(first: 50, query: $query, after: $cursor) {
    nodes {
      sku
      product { id }
    }
    pageInfo { hasNextPage endCursor }
  }
}
"""


def _shopify_sku_search_query(skus: list[str]) -> str:
    parts: list[str] = []
    for sku in skus:
        text = str(sku or "").strip()
        if not text:
            continue
        escaped = text.replace("\\", "\\\\").replace('"', '\\"')
        parts.append(f'sku:"{escaped}"')
    return " OR ".join(parts)


def fetch_remote_sku_map_for_skus(
    client,
    skus,
    *,
    chunk_size: int = 25,
    max_pages_per_chunk: int = 5,
) -> Dict[str, Optional[str]]:
    """Lookup only the requested variant SKUs (for readiness/reconcile subsets)."""
    wanted = sorted({str(sku or "").strip() for sku in skus if str(sku or "").strip()})
    if not wanted:
        return {}
    remote: Dict[str, Optional[str]] = {}
    for index in range(0, len(wanted), chunk_size):
        chunk = wanted[index : index + chunk_size]
        query = _shopify_sku_search_query(chunk)
        if not query:
            continue
        cursor: Optional[str] = None
        for _ in range(max_pages_per_chunk):
            data = client.graphql(VARIANT_SKU_LOOKUP_QUERY, {"query": query, "cursor": cursor})
            connection = data.get("productVariants") or {}
            for node in connection.get("nodes") or []:
                sku = str((node or {}).get("sku") or "").strip()
                if not sku:
                    continue
                product_id = ((node or {}).get("product") or {}).get("id")
                remote.setdefault(sku, product_id)
            page_info = connection.get("pageInfo") or {}
            if not page_info.get("hasNextPage"):
                break
            cursor = page_info.get("endCursor")
    return remote


def fetch_remote_sku_map(client, *, max_pages: int = 80) -> Dict[str, Optional[str]]:
    """All variant SKUs currently in the shop → product GID (250 per page).

    Used by reconciliation to link master SKUs to existing Shopify products.
    """
    remote: Dict[str, Optional[str]] = {}
    cursor: Optional[str] = None
    for _ in range(max_pages):
        data = client.graphql(VARIANT_SKU_PAGE_QUERY, {"cursor": cursor})
        connection = data.get("productVariants") or {}
        for node in connection.get("nodes") or []:
            sku = str((node or {}).get("sku") or "").strip()
            if not sku:
                continue
            product_id = ((node or {}).get("product") or {}).get("id")
            # First page wins on duplicate SKUs across products.
            remote.setdefault(sku, product_id)
        page_info = connection.get("pageInfo") or {}
        if not page_info.get("hasNextPage"):
            break
        cursor = page_info.get("endCursor")
    return remote
