"""
Tests for Magento inventory service (MSI detection, source-item upsert).
"""

from __future__ import annotations

from unittest.mock import MagicMock

import pytest

from magento.inventory_service import (
    InventoryUpsertResult,
    detect_inventory_mode,
    resolve_source_code,
    upsert_source_items_for_simple,
)


def test_detect_inventory_mode_msi():
    """MSI endpoints return 200 → mode=msi."""
    api = MagicMock()
    api.get_inventory_sources.return_value = (200, [{"source_code": "default"}], None)
    assert detect_inventory_mode(api, 1) == "msi"
    assert detect_inventory_mode(api, 1) == "msi"  # cached


def test_detect_inventory_mode_legacy():
    """404/501 on sources → mode=legacy."""
    api = MagicMock()
    api.get_inventory_sources.return_value = (404, [], "Not found")
    assert detect_inventory_mode(api, 2) == "legacy"


def test_upsert_source_items_simple_calls_post():
    """MSI mode: ensure_simple_sku_inventory assigns default qty when no source-items exist."""
    api = MagicMock()
    api.get_inventory_sources.return_value = (200, [{"source_code": "default", "enabled": 1}], None)
    api.get_source_items_for_skus.return_value = (200, {"CHILD-1": []}, None)  # No existing items
    api.post_source_items.return_value = (200, None)
    row = {"sku": "CHILD-1", "product_type": "simple", "qty": 5}
    result = upsert_source_items_for_simple(api, "CHILD-1", row, connection_id=1)
    assert result.msi_mode_detected is True
    assert result.source_items_written  # Uses DEFAULT_QTY (1), policy-driven
    api.post_source_items.assert_called_once()
    call_args = api.post_source_items.call_args[0][0]
    assert len(call_args) == 1
    assert call_args[0]["sku"] == "CHILD-1"
    assert call_args[0]["quantity"] >= 1  # Policy: default_qty_if_missing (1)
    assert call_args[0]["status"] == 1


def test_upsert_source_items_qty_unknown_status_zero():
    """No existing source-items → assign default qty and status=1 (policy)."""
    api = MagicMock()
    api.get_inventory_sources.return_value = (200, [{"source_code": "default"}], None)
    api.get_source_items_for_skus.return_value = (200, {"CHILD-2": []}, None)
    api.post_source_items.return_value = (200, None)
    row = {"sku": "CHILD-2", "product_type": "simple"}
    result = upsert_source_items_for_simple(api, "CHILD-2", row, connection_id=1)
    assert result.source_items_written
    assert all(si.get("status") == 1 for si in result.source_items_written)


def test_upsert_skips_configurable_parent():
    """Configurable parent: _ensure_inventory_for_simple returns early (no API call from service)."""
    from magento.sync_service import MagentoSyncService
    api = MagicMock()
    svc = MagentoSyncService(api, {"id": 1})
    row = {"sku": "PARENT", "product_type": "configurable"}
    result = svc._ensure_inventory_for_simple("PARENT", row)
    assert result.msi_mode_detected is False
    api.post_source_items.assert_not_called()


def test_resolve_source_code_uses_configured():
    """When configured_source set, use it."""
    api = MagicMock()
    assert resolve_source_code(api, 1, "homesurplus") == "homesurplus"


def test_resolve_source_code_fallback_default():
    """When no configured and API fails, use 'default'."""
    api = MagicMock()
    api.get_inventory_sources.return_value = (500, [], "Error")
    assert resolve_source_code(api, 1, None) == "default"


def test_regression_configurable_three_children_inventory_written():
    """
    Regression: configurable with 3 children - after sync we write source items for all 3.
    Admin needs source_items to show variations.
    """
    from magento.sync_service import MagentoSyncService
    api = MagicMock()
    api.put_product.return_value = (200, {})
    api.get_inventory_sources.return_value = (200, [{"source_code": "default"}], None)
    api.get_source_items_for_skus.return_value = (200, {"C1": [], "C2": [], "C3": []}, None)
    api.post_source_items.return_value = (200, None)
    api.get_configurable_children.return_value = (200, [], None)
    api.get_configurable_options.return_value = (200, [], None)

    svc = MagentoSyncService(api, {"id": 1})

    parent = {
        "sku": "PARENT",
        "name": "Parent",
        "product_type": "configurable",
        "variant_list": "C1,C2,C3",
        "configurable_attributes": "color",
        "configurable_variations": "sku=C1,color=Red|sku=C2,color=Blue|sku=C3,color=Green",
    }
    rows = [
        parent,
        {"sku": "C1", "name": "Child 1", "product_type": "simple", "variant_of": "PARENT", "qty": 1},
        {"sku": "C2", "name": "Child 2", "product_type": "simple", "variant_of": "PARENT", "qty": 0},
        {"sku": "C3", "name": "Child 3", "product_type": "simple", "variant_of": "PARENT"},
    ]
    rows_by_sku = {r["sku"]: r for r in rows}

    for row in rows:
        if "configurable" in str(row.get("product_type", "")).lower():
            continue
        inv = svc._ensure_inventory_for_simple(row["sku"], row)
        assert inv.msi_mode_detected is True
        assert inv.source_items_written, f"Child {row['sku']} must have source_items_written"

    assert api.post_source_items.call_count >= 3
