import pytest

from app.services.catalog.commercial import (
    clean_image_url, is_in_stock, price_range, resolve_product_url, to_cents,
)


@pytest.mark.parametrize("raw,expected", [
    ("9.99", 999), (9.99, 999), ("885.95", 88595), ("0", 0),
    ("2629.95", 262995), (None, None), ("", None), ("abc", None),
])
def test_to_cents(raw, expected):
    assert to_cents(raw) == expected


def test_to_cents_never_returns_a_float():
    assert isinstance(to_cents("9.99"), int)


def test_price_range_uses_min_and_max_across_variants():
    # The live Gift Card spans 10.00 to 100.00; a single price is wrong for it.
    lo, hi, cmp_at, on_sale = price_range([
        {"price": "10.00", "compare_at_price": None},
        {"price": "50.00", "compare_at_price": None},
        {"price": "100.00", "compare_at_price": None},
    ])
    assert (lo, hi) == (1000, 10000)
    assert cmp_at is None
    assert on_sale is False


def test_single_variant_has_equal_min_and_max():
    lo, hi, _, _ = price_range([{"price": "949.95", "compare_at_price": None}])
    assert lo == hi == 94995


def test_on_sale_when_compare_at_exceeds_price():
    lo, hi, cmp_at, on_sale = price_range([
        {"price": "80.00", "compare_at_price": "100.00"}])
    assert on_sale is True
    assert cmp_at == 10000


def test_compare_at_below_price_is_not_a_sale():
    _, _, _, on_sale = price_range([
        {"price": "100.00", "compare_at_price": "80.00"}])
    assert on_sale is False


def test_no_variants_yields_none():
    assert price_range([]) == (None, None, None, False)


def test_in_stock_from_availability_not_quantity():
    # Overselling merchants carry negative quantities on purchasable products.
    assert is_in_stock({"tracks_inventory": True, "variants": [
        {"available": True, "inventory_quantity": -5}]}) is True
    assert is_in_stock({"tracks_inventory": True, "variants": [
        {"available": False, "inventory_quantity": 100}]}) is False


def test_untracked_inventory_is_in_stock():
    assert is_in_stock({"tracks_inventory": False, "variants": [
        {"available": False, "inventory_quantity": 0}]}) is True


def test_any_available_variant_makes_the_product_in_stock():
    assert is_in_stock({"tracks_inventory": True, "variants": [
        {"available": False}, {"available": True}]}) is True


def test_url_prefers_the_explicit_one():
    assert resolve_product_url(
        {"product_url": "https://shop.example.com/products/x", "handle": "y"},
        primary_domain="https://shop.example.com") == \
        "https://shop.example.com/products/x"


def test_url_falls_back_to_handle():
    # All 17 live products have onlineStoreUrl null, so this is the only path.
    assert resolve_product_url(
        {"product_url": None, "handle": "the-minimal-snowboard"},
        primary_domain="https://galaxiq-braexaal.myshopify.com") == \
        "https://galaxiq-braexaal.myshopify.com/products/the-minimal-snowboard"


def test_url_template_used_for_http_sources():
    assert resolve_product_url(
        {"product_url": None, "handle": None, "external_id": 42},
        url_template="https://shop.example.com/product/{external_id}") == \
        "https://shop.example.com/product/42"


def test_url_is_none_when_nothing_resolves():
    assert resolve_product_url({"product_url": None, "handle": None}) is None


@pytest.mark.parametrize("raw,expected", [
    ("https://cdn.shopify.com/x/snowboard.jpg?v=1786334565",
     "https://cdn.shopify.com/x/snowboard.jpg"),
    ("https://cdn.shopify.com/x/snowboard_800x.jpg",
     "https://cdn.shopify.com/x/snowboard.jpg"),
    ("https://cdn.shopify.com/x/snowboard_800x600.jpg?v=1",
     "https://cdn.shopify.com/x/snowboard.jpg"),
    (None, None),
])
def test_clean_image_url(raw, expected):
    # Size suffixes and cache-busting params change between syncs and would
    # churn record_hash for no reason.
    assert clean_image_url(raw) == expected
