from unittest.mock import MagicMock, patch

from magento.collection_landing_push import (
    MAGENTO_BOOTSTRAP_MODE,
    MAGENTO_BOOTSTRAP_NOTE,
    bootstrap_magento_collection_attributes,
)
from magento.collection_landing_setup import (
    MAGENTO_SETUP_PATCH_CLASS,
    build_magento_category_attributes_data_patch,
    magento_attribute_eav_config,
    magento_eav_type,
    build_magento_collection_landing_module_files,
)


def test_magento_eav_type_mapping():
    assert magento_eav_type("boolean") == "int"
    assert magento_eav_type("textarea") == "text"
    assert magento_eav_type("text") == "varchar"


def test_magento_boolean_attribute_config_includes_source():
    config = magento_attribute_eav_config(
        {"key": "is_collection", "shopify_type": "boolean", "magento_input": "boolean"}
    )
    assert config["type"] == "int"
    assert config["input"] == "boolean"
    assert "Source\\Boolean" in config["source"]


def test_build_magento_category_attributes_data_patch_contains_all_fields():
    patch = build_magento_category_attributes_data_patch()
    assert f"class {MAGENTO_SETUP_PATCH_CLASS}" in patch
    assert "hs_page_type" in patch
    assert "hs_sibling_taxonomy_nodes" in patch
    assert "addAttribute" in patch


def test_magento_collection_module_includes_media_upload_endpoint():
    files = build_magento_collection_landing_module_files()
    assert "etc/webapi.xml" in files
    assert "etc/frontend/di.xml" in files
    assert "Controller/Router/Intersection.php" in files
    assert "Api/CollectionMediaManagementInterface.php" in files
    assert "Model/CollectionMediaManagement.php" in files
    assert "/V1/piehs/collection-media" in files["etc/webapi.xml"]
    assert "piehs/collections" in files["Model/CollectionMediaManagement.php"]
    assert "piehs_collection_intersection" in files["etc/frontend/di.xml"]
    assert "hs_shopping_intersections" in files["Controller/Router/Intersection.php"]
    assert "hs_intersection_category_id" in files["Controller/Router/Intersection.php"]


def test_magento_collection_module_emits_intersection_support_files():
    files = build_magento_collection_landing_module_files()

    assert "Plugin/Catalog/Layer/FilterListPlugin.php" in files
    assert "Plugin/Catalog/Layer/IntersectionCategoryFilterPlugin.php" in files
    assert "Plugin/Layer/StatePlugin.php" in files
    assert "view/frontend/requirejs-config.js" in files
    assert "view/frontend/web/js/submit-filter-mixin.js" in files
    assert "view/frontend/web/js/category-filters.js" not in files
    assert "addCategoriesFilter" in files["Plugin/Catalog/Layer/IntersectionCategoryFilterPlugin.php"]
    assert "hs_intersection_category_id" in files["Plugin/Catalog/Layer/IntersectionCategoryFilterPlugin.php"]
    assert "ManagedCategory" in files["Plugin/Catalog/Layer/IntersectionCategoryFilterPlugin.php"]
    assert "afterGetActiveFilters" in files["Plugin/Layer/StatePlugin.php"]
    assert "hs_intersection_category_id" in files["Plugin/Layer/StatePlugin.php"]
    assert "PieHS_CollectionLanding/js/submit-filter-mixin" in files["view/frontend/requirejs-config.js"]
    assert "piehs-managed-category" in files["view/frontend/web/js/submit-filter-mixin.js"]
    managed = files["Model/ManagedCategory.php"]
    assert "hs_is_collection" in managed
    assert "hs_taxonomy_path_slug" in managed
    assert "hasActiveChildren" not in managed
    assert "parentHasActiveChildren" not in managed


def test_magento_intersection_router_uses_dedicated_request_param():
    files = build_magento_collection_landing_module_files()
    router = files["Controller/Router/Intersection.php"]

    assert "INTERSECTION_CATEGORY_PARAM" in router
    assert "setParam(self::INTERSECTION_CATEGORY_PARAM" in router
    assert "setParam('cat'" not in router
    assert "setParam('category_ids'" not in router


def test_magento_collection_module_deploys_frontend_assets():
    from magento.collection_landing_setup import magento_collection_landing_module_deploy_instructions

    instructions = magento_collection_landing_module_deploy_instructions()
    assert "bin/magento setup:static-content:deploy -f" in instructions["commands"]
    assert "bin/magento setup:di:compile" in instructions["commands"]
    assert instructions["media_upload_route"] == "/V1/piehs/collection-media"
    assert "etc/webapi.xml" in instructions["required_media_api_files"]
    assert "Controller/Router/Intersection.php" in instructions["required_media_api_files"]
    assert "view/frontend/web/js/category-filters.js" in instructions["frontend_files_in_git_repo"]
    assert "HSMageDSCopy" in instructions["source_of_truth"]


def test_magento_collection_module_di_registers_layer_filter_plugin():
    files = build_magento_collection_landing_module_files()
    assert "FilterListPlugin" in files["etc/di.xml"]
    assert "StatePlugin" in files["etc/di.xml"]
    assert "Magento_LayeredNavigation" in files["etc/module.xml"]


def test_bootstrap_magento_discovers_existing_attributes():
    session = MagicMock()
    api = MagicMock()
    api.get_category_attribute.return_value = (
        200,
        {
            "attribute_id": 501,
            "default_frontend_label": "Brand",
            "frontend_input": "text",
            "backend_type": "varchar",
            "is_user_defined": True,
        },
    )

    with patch(
        "magento.collection_landing_push._existing_category_attribute_codes",
        return_value=set(),
    ):
        result = bootstrap_magento_collection_attributes(
            session,
            api,
            connection_id=1,
            dry_run=False,
        )

    assert result["mode"] == MAGENTO_BOOTSTRAP_MODE
    assert result["skipped"]
    assert result["created"] == []
    assert result["missing"] == []
    assert result["errors"] == []
    assert api.create_category_attribute.call_count == 0
    session.add.assert_called()
    session.flush.assert_called_once()


def test_bootstrap_magento_reports_missing_without_calling_create():
    session = MagicMock()
    api = MagicMock()
    api.get_category_attribute.return_value = (404, None)

    with patch(
        "magento.collection_landing_push._existing_category_attribute_codes",
        return_value=set(),
    ):
        result = bootstrap_magento_collection_attributes(
            session,
            api,
            connection_id=1,
            dry_run=False,
        )

    assert result["missing"]
    assert result["errors"] == []
    assert result["note"] == MAGENTO_BOOTSTRAP_NOTE
    assert result["setup_module_url"] == "/api/channel/collections/magento-attribute-module"
    api.create_category_attribute.assert_not_called()


def test_bootstrap_magento_dry_run_lists_planned_only():
    session = MagicMock()

    with patch(
        "magento.collection_landing_push._existing_category_attribute_codes",
        return_value={"hs_brand"},
    ):
        result = bootstrap_magento_collection_attributes(
            session,
            api=None,
            connection_id=1,
            dry_run=True,
        )

    assert result["planned"]
    assert result["skipped"] == ["hs_brand"]
    assert result["missing"] == []
    assert result["errors"] == []
