"""Price, stock, URL and media normalisation."""
import logging
import re

logger = logging.getLogger(__name__)

_CDN_SIZE = re.compile(r"_(\d+x\d*|\d*x\d+)(?=\.\w+\Z)")


def to_cents(price) -> int | None:
    # Integer minor units: floats accumulate rounding error across a catalog
    # and make equality comparisons between synced records unreliable.
    if price is None or price == "":
        return None
    try:
        return int(round(float(price) * 100))
    except (TypeError, ValueError):
        return None


def price_range(variants: list[dict]) -> tuple[int | None, int | None, int | None, bool]:
    prices = [c for c in (to_cents(v.get("price")) for v in variants or [])
              if c is not None]
    if not prices:
        return None, None, None, False

    lo, hi = min(prices), max(prices)

    compare_at, on_sale = None, False
    for v in variants:
        cmp_c, price_c = to_cents(v.get("compare_at_price")), to_cents(v.get("price"))
        # A compare-at at or below price is bad merchant data, not a
        # discount; treating it as one would show a fake markdown.
        if cmp_c is not None and price_c is not None and cmp_c > price_c:
            on_sale = True
            compare_at = cmp_c if compare_at is None else max(compare_at, cmp_c)

    return lo, hi, compare_at, on_sale


def is_in_stock(source_product: dict) -> bool:
    # Availability flag only, never inventory_quantity: merchants with
    # overselling enabled carry negative quantities on purchasable products.
    if not source_product.get("tracks_inventory"):
        return True
    return any(v.get("available") for v in source_product.get("variants") or [])


def resolve_product_url(
    source_product: dict, primary_domain: str | None = None, url_template: str | None = None
) -> str | None:
    explicit = source_product.get("product_url")
    if explicit:
        return explicit

    handle = source_product.get("handle")
    if handle and primary_domain:
        return f"{primary_domain.rstrip('/')}/products/{handle}"

    if url_template:
        try:
            return url_template.format(**source_product)
        except (KeyError, IndexError):
            logger.warning("url_template does not match the record's fields")
            return None

    return None


def clean_image_url(url: str | None) -> str | None:
    # Shopify CDN size suffixes and query params change between syncs and
    # would otherwise churn record_hash for no reason.
    if not url:
        return None
    return _CDN_SIZE.sub("", url.split("?")[0])
