"""UPSERT_PRODUCT must not POST-create when the SKU already exists."""

from __future__ import annotations

from unittest.mock import MagicMock

from magento.sync_service import (
    MagentoSyncService,
    _is_ambiguous_missing_product_put_error,
    _is_sku_already_exists_error,
)


def _svc(api: MagicMock) -> MagentoSyncService:
    svc = MagentoSyncService(api, {"id": 1})
    svc._build_put_payload_for_upsert = MagicMock(  # type: ignore[method-assign]
        return_value={"sku": "RTA-GSW-OC3384", "name": "Oven Cabinet", "status": 1}
    )
    svc._build_create_payload_for_upsert = MagicMock(  # type: ignore[method-assign]
        return_value={
            "sku": "RTA-GSW-OC3384",
            "name": "Oven Cabinet",
            "status": 1,
            "attribute_set_id": 4,
            "type_id": "simple",
        }
    )
    svc._ensure_inventory_for_simple = MagicMock(return_value=MagicMock())  # type: ignore[method-assign]
    svc._call_with_retry = lambda _name, fn: fn()  # type: ignore[method-assign]
    return svc


def test_sku_already_exists_helpers():
    assert _is_sku_already_exists_error(
        400, {"message": "Product with the same sku already exists"}
    )
    assert not _is_sku_already_exists_error(
        400, {"message": "URL key for specified store already exists"}
    )
    assert _is_ambiguous_missing_product_put_error(
        400, {"message": "Invalid product data"}
    )
    assert not _is_ambiguous_missing_product_put_error(404, {"message": "Not found"})


def test_put_404_then_get_exists_retries_put_not_post():
    api = MagicMock()
    api.put_product.side_effect = [
        (404, {"message": "Requested product doesn't exist"}),
        (200, {"sku": "RTA-GSW-OC3384", "id": 18670}),
    ]
    api.get_product.return_value = {"sku": "RTA-GSW-OC3384", "id": 18670}

    svc = _svc(api)
    result = svc.execute_upsert_product(
        "RTA-GSW-OC3384",
        {"sku": "RTA-GSW-OC3384"},
        {"sku": "RTA-GSW-OC3384", "name": "Oven Cabinet"},
    )

    assert result["status"] == "success"
    assert result["is_new"] is False
    assert api.post_product.call_count == 0
    assert api.put_product.call_count == 2


def test_invalid_product_data_on_existing_refuses_create():
    api = MagicMock()
    api.put_product.return_value = (400, {"message": "Invalid product data"})
    api.get_product.return_value = {"sku": "RTA-GSW-OC3384", "id": 18670}

    svc = _svc(api)
    result = svc.execute_upsert_product(
        "RTA-GSW-OC3384",
        {"sku": "RTA-GSW-OC3384"},
        {"sku": "RTA-GSW-OC3384"},
    )

    assert result["status"] == "failed"
    assert result["is_new"] is False
    assert "refusing POST create" in result["error"]
    api.post_product.assert_not_called()


def test_post_sku_already_exists_falls_back_to_put():
    api = MagicMock()
    api.put_product.side_effect = [
        (404, {"message": "Requested product doesn't exist"}),
        (200, {"sku": "RTA-GSW-OC3384", "id": 18670}),
    ]
    # First GET (before create) missing; second GET (before POST) missing; then POST exists.
    api.get_product.side_effect = [None, None, {"sku": "RTA-GSW-OC3384", "id": 18670}]
    api.post_product.return_value = (
        400,
        {"message": "A product with the same SKU already exists."},
    )

    svc = _svc(api)
    result = svc.execute_upsert_product(
        "RTA-GSW-OC3384",
        {"sku": "RTA-GSW-OC3384"},
        {"sku": "RTA-GSW-OC3384"},
    )

    assert result["status"] == "success"
    assert result["is_new"] is False
    assert api.post_product.call_count == 1
    assert api.put_product.call_count == 2


def test_confirmed_missing_still_creates():
    api = MagicMock()
    api.put_product.return_value = (404, {"message": "Requested product doesn't exist"})
    api.get_product.side_effect = [None, None, {"sku": "NEW-1", "id": 1}]
    api.post_product.return_value = (201, {"sku": "NEW-1", "id": 1})

    svc = _svc(api)
    result = svc.execute_upsert_product(
        "NEW-1",
        {"sku": "NEW-1"},
        {"sku": "NEW-1", "name": "New"},
    )

    assert result["status"] == "success"
    assert result["is_new"] is True
    api.post_product.assert_called_once()
