import ast
import json
import tempfile
import unittest
from pathlib import Path


REPO_ROOT = Path(__file__).resolve().parents[1]
LAYOUT_MANAGER = REPO_ROOT / "LayoutManager.py"


def load_layout_as_dict(layout_dir):
    tree = ast.parse(LAYOUT_MANAGER.read_text(encoding="utf-8"))
    function = next(
        node for node in tree.body
        if isinstance(node, ast.FunctionDef) and node.name == "layout_as_dict"
    )
    namespace = {
        "json": json,
        "os": __import__("os"),
        "_LAYOUTS_UI": str(layout_dir),
        "_extension_settings": {
            "dash-to-dock@micxgx.gmail.com": None,
            "arcmenu@arcmenu.com": None,
            "just-perfection-desktop@just-perfection": None,
            "gtk4-ding@smedius.gitlab.com": None,
        },
    }
    exec(compile(ast.Module(body=[function], type_ignores=[]), str(LAYOUT_MANAGER), "exec"), namespace)
    return namespace["layout_as_dict"]


class LayoutDependencyTests(unittest.TestCase):
    def test_schema_less_extension_declared_by_layout_is_enabled(self):
        with tempfile.TemporaryDirectory() as tmp:
            layout_dir = Path(tmp)
            cupertino = {
                "name": "Cupertino",
                "dash-to-dock@micxgx.gmail.com": {},
                "Move_Clock@rmy.pobox.com": None,
            }
            (layout_dir / "cupertino.json").write_text(json.dumps(cupertino), encoding="utf-8")

            parsed = load_layout_as_dict(layout_dir)(json.dumps(cupertino))

            self.assertIn("Move_Clock@rmy.pobox.com", parsed["enabled_extensions"])

    def test_schema_less_extension_is_disabled_when_switching_to_another_layout(self):
        with tempfile.TemporaryDirectory() as tmp:
            layout_dir = Path(tmp)
            cupertino = {
                "name": "Cupertino",
                "dash-to-dock@micxgx.gmail.com": {},
                "Move_Clock@rmy.pobox.com": None,
            }
            vanilla = {"name": "Vanilla"}
            (layout_dir / "cupertino.json").write_text(json.dumps(cupertino), encoding="utf-8")
            (layout_dir / "vanilla.json").write_text(json.dumps(vanilla), encoding="utf-8")

            parsed = load_layout_as_dict(layout_dir)(json.dumps(vanilla))

            self.assertIn("Move_Clock@rmy.pobox.com", parsed["disabled_extensions"])

    def test_explicit_schema_less_extension_is_disabled_after_switching_layouts(self):
        with tempfile.TemporaryDirectory() as tmp:
            layout_dir = Path(tmp)
            extension = "SchemaLess@example.org"
            custom = {
                "name": "Custom",
                "enabled_extensions": [extension],
            }
            vanilla = {"name": "Vanilla"}
            (layout_dir / "custom.json").write_text(json.dumps(custom), encoding="utf-8")
            (layout_dir / "vanilla.json").write_text(json.dumps(vanilla), encoding="utf-8")

            parsed = load_layout_as_dict(layout_dir)(json.dumps(vanilla))

            self.assertIn(extension, parsed["disabled_extensions"])

    def test_explicit_schema_less_extension_lists_are_deduplicated_and_enabled_wins(self):
        with tempfile.TemporaryDirectory() as tmp:
            layout_dir = Path(tmp)
            extension = "SchemaLess@example.org"
            layout = {
                "name": "Conflict",
                "enabled_extensions": [extension, extension],
                "disabled_extensions": [extension, extension],
            }
            (layout_dir / "conflict.json").write_text(json.dumps(layout), encoding="utf-8")

            parsed = load_layout_as_dict(layout_dir)(json.dumps(layout))

            self.assertEqual(parsed["enabled_extensions"].count(extension), 1)
            self.assertNotIn(extension, parsed["disabled_extensions"])


if __name__ == "__main__":
    unittest.main()
