# Copyright: (c) 2025, Luca Bilke <luca@bil.ke>
# MIT License (see LICENSE)

from typing import Any
from unittest import TestCase

import pytest
from ansible_collections.snailed.ez_compose.plugins.module_utils import common


@pytest.mark.parametrize(
    ("test_input", "expected"),
    [  # pyright: ignore[reportUnknownArgumentType]
        # Basic nested update (using existing test variables)
        (
            (
                {"one": {"one": "keep", "two": "rewrite"}},
                {"one": {"two": "new"}},
            ),
            {"one": {"one": "keep", "two": "new"}},
        ),
        # Deep nested update
        (
            (
                {"a": {"b": {"c": "old", "d": "keep"}}},
                {"a": {"b": {"c": "new"}}},
            ),
            {"a": {"b": {"c": "new", "d": "keep"}}},
        ),
        # Adding new keys at different levels
        (
            (
                {"x": {"y": "original"}},
                {"x": {"z": "new", "y": "updated"}, "new_key": "value"},
            ),
            {"x": {"y": "updated", "z": "new"}, "new_key": "value"},
        ),
        # Empty dict cases
        (
            (
                {},
                {"new": "data"},
            ),
            {"new": "data"},
        ),
        (
            (
                {"existing": "data"},
                {},
            ),
            {"existing": "data"},
        ),
        # Lists within dictionaries
        (
            (
                {"items": ["a", "b"], "nested": {"list": ["1", "2"]}},
                {"items": ["c"], "nested": {"list": ["3"]}},
            ),
            {"items": ["a", "b", "c"], "nested": {"list": ["1", "2", "3"]}},
        ),
        # Lists of dictionaries
        (
            (
                {
                    "configs": [
                        {"name": "config1", "value": "old"},
                        {"name": "config2", "enabled": True},
                    ],
                },
                {
                    "configs": [
                        {"name": "config3", "value": "new"},
                        {"name": "config4", "enabled": False},
                    ],
                },
            ),
            {
                "configs": [
                    {"name": "config1", "value": "old"},
                    {"name": "config2", "enabled": True},
                    {"name": "config3", "value": "new"},
                    {"name": "config4", "enabled": False},
                ],
            },
        ),
        # Nested lists of dictionaries
        (
            (
                {
                    "services": {
                        "web": [
                            {"port": 80, "protocol": "http"},
                            {"port": 443, "protocol": "https"},
                        ],
                    },
                },
                {"services": {"web": [{"port": 8080, "protocol": "http"}]}},
            ),
            {
                "services": {
                    "web": [
                        {"port": 80, "protocol": "http"},
                        {"port": 443, "protocol": "https"},
                        {"port": 8080, "protocol": "http"},
                    ],
                },
            },
        ),
        # Mixed types update
        (
            (
                {"mixed": {"num": 42, "list": [1, 2], "str": "old"}},
                {"mixed": {"num": 43, "list": [3], "str": "new"}},
            ),
            {"mixed": {"num": 43, "list": [1, 2, 3], "str": "new"}},
        ),
    ],
)
def test_recursive_update(
    test_input: tuple[dict[str, Any], dict[str, Any]],
    expected: dict[str, Any],
) -> None:
    TestCase().assertDictEqual(common.recursive_update(*test_input), expected)