import pytest

from app.services.catalog.fieldmap import (
    FieldMapError, apply_field_map, resolve_path,
)

RECORD = {
    "id": 1,
    "title": "Essence Mascara Lash Princess",
    "price": 9.99,
    "dimensions": {"width": 15.14, "height": 13.08},
    "images": ["https://cdn.example.com/1.webp", "https://cdn.example.com/2.webp"],
    "tags": ["beauty", "mascara"],
    "meta": {"barcode": "5784719087687"},
    "empty": None,
}


@pytest.mark.parametrize("path,expected", [
    ("$.id", 1),
    ("$.title", "Essence Mascara Lash Princess"),
    ("$.price", 9.99),
    ("$.dimensions.width", 15.14),
    ("$.images[0]", "https://cdn.example.com/1.webp"),
    ("$.images[1]", "https://cdn.example.com/2.webp"),
    ("$.meta.barcode", "5784719087687"),
    ("$.tags", ["beauty", "mascara"]),
    ("$.empty", None),
])
def test_resolve_path(path, expected):
    assert resolve_path(RECORD, path) == expected


@pytest.mark.parametrize("path", [
    "$.missing",
    "$.dimensions.depth",
    "$.images[9]",
    "$.title.nested",
    "$.tags[0].deeper",
])
def test_missing_paths_return_none_rather_than_raising(path):
    # A merchant API with a sparse record must degrade, not abort the sync.
    assert resolve_path(RECORD, path) is None


@pytest.mark.parametrize("path", ["title", "", "$", "$..title", None])
def test_malformed_paths_raise(path):
    with pytest.raises(FieldMapError):
        resolve_path(RECORD, path)


def test_apply_field_map():
    out = apply_field_map(RECORD, {
        "external_id": "$.id",
        "title": "$.title",
        "price": "$.price",
        "image_url": "$.images[0]",
        "tags": "$.tags",
        "brand": "$.missing",
    })
    assert out == {
        "external_id": 1,
        "title": "Essence Mascara Lash Princess",
        "price": 9.99,
        "image_url": "https://cdn.example.com/1.webp",
        "tags": ["beauty", "mascara"],
        "brand": None,
    }


def test_apply_field_map_rejects_a_bad_path_loudly():
    # A typo in a stored config must surface at sync time, not silently null a field.
    with pytest.raises(FieldMapError):
        apply_field_map(RECORD, {"title": "title"})
