"""Every catalogue reader shows a picture through the one cascade (Stream AW3.3).

`catalog_queries.pictures_of` takes the rows a page lists and answers, per product variant, the
picture it shows: its own, else its product line's, else its brand's, with the level exposed,
in one query for the lines and one for the brands. Pinned: a variant with no picture under a
line with one shows the line's at level `line`; under a bare line, the brand's at level
`brand`; a variant's own picture wins; an alias line and an alias brand are followed to the
fold row the picture is set on; a variant with no line still reaches its brand; and the picture
fields a summary carries come out of one Picture. What the wrong answer costs: a brand mark
emitted as a bottle's `image`, or a page of grey monograms beside a catalogue that holds the
line's picture.
"""

from __future__ import annotations

import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool

from app.models import Base, Brand, ProductLine, ProductVariant
from app.services import catalog_queries, imagery

TABLES = [Brand.__table__, ProductLine.__table__, ProductVariant.__table__]


def _variant(id, line_id, brand_id, **kw):
    return ProductVariant(id=id, name=f"v{id}", brand="B", brand_id=brand_id, product_line_id=line_id,
                          quantity_ml=700, match_key=f"k{id}", attributes={}, **kw)


@pytest.fixture
def db():
    engine = create_engine("sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool)
    Base.metadata.create_all(engine, tables=TABLES)
    factory = sessionmaker(bind=engine, autoflush=False, expire_on_commit=False, future=True)
    with factory() as session:
        session.add_all([
            Brand(id=1, slug="glenfiddich", name="Glenfiddich", image_url="/uploads/images/brand/glenfiddich-a.webp",
                  thumb_url="/uploads/images/brand/glenfiddich-a-thumb.webp", image_source="admin:pernod-ricard-via-adam", image_level="brand"),
            Brand(id=2, slug="glenfiddich-old", name="GLENFIDDICH", alias_of_id=1),
            Brand(id=3, slug="nobody", name="Nobody"),
        ])
        session.flush()
        session.add_all([
            ProductLine(id=11, brand_id=1, key="15yo", name="15", slug="g-15", image_url="/uploads/images/line/g-15-b.webp",
                        thumb_url="/uploads/images/line/g-15-b-thumb.webp", image_source="admin:william-grant-via-adam", image_level="line"),
            ProductLine(id=12, brand_id=1, key="18yo", name="18", slug="g-18"),
            ProductLine(id=13, brand_id=1, key="15 yo", name="15 alias", slug="g-15-alias", alias_of_id=11),
            ProductLine(id=31, brand_id=3, key="x", name="x", slug="n-x"),
        ])
        session.flush()
        session.add_all([
            _variant(1, 11, 1),  # no picture of its own: the line's
            _variant(2, 12, 1),  # a bare line: the brand's
            _variant(3, 11, 1, image_url="https://off.example/3.jpg", thumb_url="https://off.example/3-t.jpg",
                     image_source=imagery.PUBLIC_OFF_BARCODE, image_level="variant"),
            _variant(4, 13, 2),  # an alias line under an alias brand
            _variant(5, None, 1),  # no line at all
            _variant(6, 31, 3),  # nothing anywhere
        ])
        session.flush()
        yield session


def test_the_cascade_per_variant_with_the_level_exposed(db):
    rows = db.query(ProductVariant).order_by(ProductVariant.id).all()
    pictures = catalog_queries.pictures_of(db, rows)
    assert (pictures[1].url, pictures[1].level, pictures[1].credit) == ("/uploads/images/line/g-15-b.webp", "line", "William Grant")
    assert (pictures[2].url, pictures[2].level, pictures[2].credit) == ("/uploads/images/brand/glenfiddich-a.webp", "brand", "Pernod Ricard")
    assert (pictures[3].url, pictures[3].level, pictures[3].credit) == ("https://off.example/3.jpg", "variant", "Open Food Facts")
    assert (pictures[4].url, pictures[4].level) == ("/uploads/images/line/g-15-b.webp", "line")
    assert (pictures[5].url, pictures[5].level) == ("/uploads/images/brand/glenfiddich-a.webp", "brand")
    assert pictures[6] is None


def test_the_fields_a_summary_carries_come_from_one_picture(db):
    rows = db.query(ProductVariant).order_by(ProductVariant.id).all()
    fields = catalog_queries.picture_fields(catalog_queries.pictures_of(db, rows)[2])
    assert fields == {"thumb_url": "/uploads/images/brand/glenfiddich-a-thumb.webp", "image_url": "/uploads/images/brand/glenfiddich-a.webp",
                      "image_source": "admin:pernod-ricard-via-adam", "image_level": "brand", "image_credit": "Pernod Ricard"}
    assert catalog_queries.picture_fields(None) == {}


def test_no_rows_asks_the_database_nothing():
    class NoDb:
        pass

    assert catalog_queries.pictures_of(NoDb(), []) == {}
