"""Unit tests for Magento status/visibility-only repair (no MSI/price)."""

from __future__ import annotations

from app.jobs.magento_fix_status_visibility import (
    VISIBILITY_CATALOG_SEARCH,
    VISIBILITY_NOT_VISIBLE,
    build_status_visibility_fixes,
    push_status_visibility_fixes,
)


def test_build_roles_parent_child_simple():
    products = [
        {
            "sku": "PARENT-1",
            "type_id": "configurable",
            "attribute_set_id": 4,
            "status": 2,
            "visibility": 1,
            "custom_attributes": [{"attribute_code": "url_key", "value": "parent-1"}],
        },
        {
            "sku": "CHILD-1",
            "type_id": "simple",
            "attribute_set_id": 4,
            "status": 1,
            "visibility": 4,
        },
        {
            "sku": "SOLO-1",
            "type_id": "simple",
            "attribute_set_id": 4,
            "status": 2,
            "visibility": 1,
        },
    ]
    fixes = build_status_visibility_fixes(products, {"CHILD-1"})
    by_sku = {f.sku: f for f in fixes}

    assert by_sku["PARENT-1"].role == "parent"
    assert by_sku["PARENT-1"].url_key == "parent-1"
    assert by_sku["PARENT-1"].target_visibility == VISIBILITY_CATALOG_SEARCH
    assert by_sku["PARENT-1"].needs_update is True

    assert by_sku["CHILD-1"].role == "child"
    assert by_sku["CHILD-1"].target_visibility == VISIBILITY_NOT_VISIBLE

    assert by_sku["SOLO-1"].role == "simple"
    assert by_sku["SOLO-1"].target_visibility == VISIBILITY_CATALOG_SEARCH


def test_push_only_sends_status_visibility_and_identity():
    class FakeApi:
        def __init__(self) -> None:
            self.puts = []
            self.posts = []

        def put_product(self, sku, payload):
            self.puts.append((sku, payload))
            return 200, {"sku": sku}

        def post_product(self, payload):
            self.posts.append(payload)
            return 200, payload

    products = [
        {
            "sku": "SOLO-1",
            "type_id": "simple",
            "attribute_set_id": 9,
            "status": 2,
            "visibility": 1,
            "custom_attributes": [{"attribute_code": "url_key", "value": "solo-1"}],
        },
        {
            "sku": "OK-1",
            "type_id": "simple",
            "attribute_set_id": 9,
            "status": 1,
            "visibility": 4,
        },
    ]
    fixes = build_status_visibility_fixes(products, set())
    api = FakeApi()
    result = push_status_visibility_fixes(api, fixes, dry_run=False)

    assert result["updated"] == 1
    assert result["skipped_already_ok"] == 1
    assert api.puts[0][1]["status"] == 1
    assert api.puts[0][1]["visibility"] == 4
    assert api.puts[0][1]["attribute_set_id"] == 9
    assert api.puts[0][1]["custom_attributes"] == [
        {"attribute_code": "url_key", "value": "solo-1"}
    ]
    assert "price" not in api.puts[0][1]


def test_slash_sku_retries_post_on_invalid_attribute_set():
    class FakeApi:
        def __init__(self) -> None:
            self.puts = []
            self.posts = []

        def put_product(self, sku, payload):
            self.puts.append((sku, payload))
            return 400, {
                "message": "Invalid product data: %1",
                "parameters": ["Invalid attribute set entity type"],
            }

        def post_product(self, payload):
            self.posts.append(payload)
            return 200, payload

    products = [
        {
            "sku": "HPW-BBC45/48FHL/R-MC",
            "type_id": "simple",
            "attribute_set_id": 4,
            "status": 2,
            "visibility": 1,
        }
    ]
    fixes = build_status_visibility_fixes(products, set())
    api = FakeApi()
    result = push_status_visibility_fixes(api, fixes, dry_run=False)

    assert result["updated"] == 1
    assert result["error_count"] == 0
    assert len(api.posts) == 1
    assert api.posts[0]["sku"] == "HPW-BBC45/48FHL/R-MC"


def test_url_key_conflict_retries_with_unique_sku_slug():
    class FakeApi:
        def __init__(self) -> None:
            self.puts = []

        def put_product(self, sku, payload):
            self.puts.append((sku, dict(payload)))
            url_attrs = {
                a.get("value")
                for a in (payload.get("custom_attributes") or [])
                if a.get("attribute_code") == "url_key"
            }
            if url_attrs == {"asw-mwep36"} or not url_attrs:
                return 400, {"message": "URL key for specified store already exists."}
            return 200, {"sku": sku}

        def post_product(self, payload):
            return 400, payload

    products = [
        {
            "sku": "ASW-MWEP36",
            "type_id": "simple",
            "attribute_set_id": 4,
            "status": 2,
            "visibility": 1,
            "custom_attributes": [{"attribute_code": "url_key", "value": "asw-mwep36"}],
        }
    ]
    fixes = build_status_visibility_fixes(products, set())
    api = FakeApi()
    result = push_status_visibility_fixes(api, fixes, dry_run=False)

    assert result["updated"] == 1
    assert result["error_count"] == 0
    assert len(api.puts) >= 2
    last_url = {
        a.get("value")
        for a in (api.puts[-1][1].get("custom_attributes") or [])
        if a.get("attribute_code") == "url_key"
    }
    assert last_url == {"asw-mwep36-sku"}
