import os
import sys
import json
import tempfile
import shutil
import unittest
from unittest.mock import patch

# Absolute path to the tree.py script
SCRIPT_PATH = os.path.abspath(
    os.path.join(os.path.dirname(__file__), "../../../../cli/build/tree.py")
)

class TestTreeShadowFolder(unittest.TestCase):
    def setUp(self):
        # Create a temporary roles directory and a dummy role
        self.roles_dir = tempfile.mkdtemp()
        self.role_name = "dummyrole"
        self.role_path = os.path.join(self.roles_dir, self.role_name)
        os.makedirs(os.path.join(self.role_path, "meta"))

        # Create a temporary shadow folder
        self.shadow_dir = tempfile.mkdtemp()

        # Patch sys.argv so the script picks up our dirs
        self.orig_argv = sys.argv[:]
        sys.argv = [
            SCRIPT_PATH,
            "-d", self.roles_dir,
            "-s", self.shadow_dir,
            "-o", "json"
        ]

        # Ensure project root is on sys.path so `import cli.build.tree` works
        project_root = os.path.abspath(
            os.path.join(os.path.dirname(__file__), "../../../../")
        )
        if project_root not in sys.path:
            sys.path.insert(0, project_root)

    def tearDown(self):
        # Restore original argv and clean up
        sys.argv = self.orig_argv
        shutil.rmtree(self.roles_dir)
        shutil.rmtree(self.shadow_dir)

    @patch("cli.build.tree.build_mappings")
    @patch("cli.build.tree.output_graph")
    def test_tree_json_written_to_shadow_folder(self, mock_output_graph, mock_build_mappings):
        # Prepare the dummy graph that build_mappings should return
        dummy_graph = {"dummy": {"test": 42}}
        mock_build_mappings.return_value = dummy_graph

        # Import the script module by name (so our @patch applies) and call main()
        import importlib
        tree_mod = importlib.import_module("cli.build.tree")
        tree_mod.main()

        # Verify that tree.json was written into the shadow folder
        expected_tree_path = os.path.join(
            self.shadow_dir, self.role_name, "meta", "tree.json"
        )
        self.assertTrue(
            os.path.isfile(expected_tree_path),
            f"tree.json not found at {expected_tree_path}"
        )

        # Verify contents match our dummy_graph
        with open(expected_tree_path, 'r') as f:
            data = json.load(f)
        self.assertEqual(data, dummy_graph, "tree.json content mismatch")

        # Ensure that no tree.json was written to the real meta/ folder
        original_tree_path = os.path.join(self.role_path, "meta", "tree.json")
        self.assertFalse(
            os.path.exists(original_tree_path),
            "tree.json should NOT be written to the real meta/ folder"
        )

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