"""Reading prices off the Avolta storefront platform.

Three shipped incidents live here: a promoted product recorded at its
pre-promotion price, a whole store recorded in the wrong currency, and a
multi-size product recorded at its smallest variant's price.
"""

from pathlib import Path

import pytest

from app.services.collectors.avolta import (
    _CONFIGURABLE_SUFFIX,
    declared_currency,
    parse_products,
    size_label,
    variant_prices,
)

FIXTURES = Path(__file__).parent / "fixtures"


def tile(*, sku="5000267023625", name="Some Whisky 1L", price_block="", url="https://x/en/1/p"):
    return f'''<div class="product-item-info">
      <a class="product-item-link" href="{url}">{name}</a>
      {price_block}
      <span data-product-sku="{sku}"></span></div>'''


class TestPriceExtraction:
    def test_prefers_the_selling_price_over_the_crossed_out_one(self):
        """This platform renders oldPrice BEFORE finalPrice, so taking the first
        price on the tile published a 20%-off Laphroaig at its full price."""
        html = tile(price_block='''
          <span data-price-type="oldPrice" data-price-amount="47.79">£47.79</span>
          <span data-price-type="finalPrice" data-price-amount="38.232">£38.23</span>''')
        item = parse_products(html)[0]
        assert item["price"] == 38.23  # rounded to the displayed pence
        assert item["was_price"] == 47.79

    def test_a_plain_tile_still_parses(self):
        html = tile(price_block='<span data-price-amount="299.00">£299</span>')
        item = parse_products(html)[0]
        assert item["price"] == 299.0
        assert item["was_price"] is None

    def test_a_was_price_below_the_selling_price_is_dropped(self):
        """Some shops render a 'was' equal to or under the current price;
        showing that as a saving would be wrong."""
        html = tile(price_block='''
          <span data-price-type="oldPrice" data-price-amount="10.00">£10</span>
          <span data-price-type="finalPrice" data-price-amount="12.00">£12</span>''')
        assert parse_products(html)[0]["was_price"] is None

    def test_a_tile_without_a_price_is_skipped(self):
        assert parse_products(tile(price_block="")) == []


class TestCurrency:
    def test_the_page_declaration_beats_the_symbol(self):
        """One store displays 'US$308.00' beside 'MX$5,390.00'. Reading the '$'
        and applying the store's default recorded the dollar figure as pesos,
        publishing that whole shop at a seventeenth of its real prices."""
        assert declared_currency('<meta itemprop="priceCurrency" content="USD"/>') == "USD"

    def test_reads_the_json_form_too(self):
        assert declared_currency('{"priceCurrency":"CHF"}') == "CHF"

    def test_absent_declaration_returns_none(self):
        """None means 'fall back to the symbol map', not 'no currency'."""
        assert declared_currency("<div>no currency here</div>") is None


class TestConfigurableProducts:
    """A multi-size tile advertises its CHEAPEST variant. Heathrow lists Johnnie
    Walker Blue Label 1L at the 20cl price; the per-size truth is only on the
    product page."""

    @pytest.fixture
    def product_page(self):
        return (FIXTURES / "avolta_configurable_product.html").read_text()

    def test_reads_the_price_of_each_size(self, product_page):
        assert variant_prices(product_page) == {1000: (199.0, 200.69), 200: (54.59, None)}

    def test_the_litre_is_not_the_advertised_tile_price(self, product_page):
        """The regression in one line: the tile said 54.59, the litre is 199."""
        assert variant_prices(product_page)[1000][0] != 54.59

    def test_unparseable_markup_yields_nothing(self):
        """Empty means 'could not resolve', and the collector then keeps the tile
        price rather than dropping the listing."""
        assert variant_prices("<html><body>no config here</body></html>") == {}

    def test_parent_skus_are_recognised(self):
        assert "2020675100063-P".endswith(_CONFIGURABLE_SUFFIX)
        assert not "2070364000006".endswith(_CONFIGURABLE_SUFFIX)


class TestVariantEmission:
    """A multi-size tile is a family of products; each priced size becomes its
    own listing. Which size a tile's own price means differs per store, so the
    tile price is never published as-is for configurables."""

    def test_size_labels_read_like_bottles(self):
        assert size_label(1500) == "1.5L"
        assert size_label(750) == "75cl"
        assert size_label(200) == "20cl"
        assert size_label(50) == "5cl"
        assert size_label(1000) == "1L"

    def test_variant_listings_carry_no_barcode(self):
        from app.services.collectors.avolta import STORES, AvoltaCollector

        collector = AvoltaCollector(STORES[0])
        item = {"sku": "5490771-P::1500", "name": "Armand de Brignac Gold 1.5L",
                "brand": "Armand de Brignac", "url": "https://x/en/1/armand-15l"}
        listing = collector._listing(item, "CHF", "https://x/en/1/champagne", 598.4, None)
        assert listing.gtin is None
        assert listing.source_sku == "5490771-P::1500"
        assert listing.size_ml == 1500  # from the name suffix

    def test_a_parent_sku_with_real_ean_digits_still_resolves_for_simple_tiles(self):
        from app.services.collectors.avolta import STORES, AvoltaCollector

        collector = AvoltaCollector(STORES[0])
        item = {"sku": "5000267023625", "name": "JW Black 1L", "brand": None,
                "url": "https://x/en/1/jw-black-1l"}
        listing = collector._listing(item, "GBP", "https://x/en/1/whisky", 30.0, None)
        assert listing.gtin == "5000267023625"
