import json
import shutil
import sys
import unittest
from datetime import UTC, datetime
from pathlib import Path

# Détermination du dossier racine du projet pour garantir le bon fonctionnement des imports
PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

from core.domain.umc_operations import add_category, add_map_to_category
from core.io.umc_parser import parse_umc_file
from core.io.umc_writer import write


class TestCSSModCategorieManager(unittest.TestCase):
    """Sandbox-based unit testing system for UMC configuration management."""

    def setUp(self):
        """Initialize the sandbox environment before each test."""
        self.results_dir = Path(__file__).parent / "results_sandbox"
        self.results_dir.mkdir(parents=True, exist_ok=True)

        self.timestamp = datetime.now(tz=UTC).strftime("%Y-%m-%d_%H-%M-%S")
        self.sandbox_file = self.results_dir / f"sandbox_input_{self.timestamp}.txt"

        initial_content = '"umc_mapcycle"\n{\n\t"Normal"\n\t{\n\t}\n}\n'
        self.sandbox_file.write_text(initial_content, encoding="utf-8")
        self.sandbox_file.write_text(initial_content, encoding="utf-8")

        self.data = parse_umc_file(self.sandbox_file)

    def tearDown(self):
        """Thorough cleaning of the sandbox after each test."""
        if self.results_dir.exists():
            shutil.rmtree(self.results_dir)

    def test_initial_state(self):
        """Verify that the initial configuration of the Sandbox is correct."""
        self.assertIn("Normal", self.data)
        category_content = self.data["Normal"]

        self.assertIn("maps", category_content)
        actual_maps = category_content["maps"]

        self.assertEqual(
            len(actual_maps),
            0,
            f"Error: The maps dictionary contains {len(actual_maps)} elements instead of 0. Content: {actual_maps}",
        )

    def test_add_map_to_existing_category(self):
        """Test the simple process of adding a map to an existing category."""
        add_map_to_category(self.data, "Normal", "de_test_simple")

        self.assertIn("de_test_simple", self.data["Normal"]["maps"])
        self.assertEqual(self.data["Normal"]["maps"]["de_test_simple"], {})

    def test_add_new_category_and_map(self):
        """Test creating a category and adding a map to it."""
        add_category(self.data, "TEST_CATEGORY")
        self.assertIn("TEST_CATEGORY", self.data)

        add_map_to_category(self.data, "TEST_CATEGORY", "de_test_category")
        self.assertIn("de_test_category", self.data["TEST_CATEGORY"]["maps"])

    def test_add_map_with_complex_options(self):
        """Test inserting a map with a dictionary of complex options."""
        map_options = {
            "display": "Map de test options",
            "tier": "3",
            "min_players": "4",
            "max_players": "24",
            "weight": "5",
        }
        add_category(self.data, "TEST_CATEGORY")
        add_map_to_category(self.data, "TEST_CATEGORY", "de_test_options", map_options)

        maps_dict = self.data["TEST_CATEGORY"]["maps"]
        self.assertIn("de_test_options", maps_dict)
        self.assertEqual(maps_dict["de_test_options"]["tier"], "3")
        self.assertEqual(maps_dict["de_test_options"]["max_players"], "24")

    def test_serialization_and_writer(self):
        """Verify that UMCWriter actually generates the expected files."""
        add_map_to_category(self.data, "Normal", "de_serialization_test")

        json_output = self.results_dir / f"result_{self.timestamp}.json"
        umc_output = self.results_dir / f"result_{self.timestamp}.txt"

        with open(json_output, "w", encoding="utf-8") as f:
            json.dump(self.data, f, indent=4, ensure_ascii=False)

        write(umc_output, self.data, create_backup=False)

        self.assertTrue(json_output.exists())
        self.assertTrue(umc_output.exists())


if __name__ == "__main__":
    unittest.main()
