import sys
import unittest
from datetime import UTC, datetime
from pathlib import Path

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.exceptions import CategoryAlreadyExists, MapAlreadyExists, ValidationError
from core.io.umc_parser import parse_umc_file


class TestCSSModCategorieManagerErrors(unittest.TestCase):
    """A unit testing system in Sandbox that validates the handling of security exceptions."""

    def setUp(self):
        """Initialize the sandbox environment before each error 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_errors_{self.timestamp}.txt"

        initial_content = (
            '"umc_mapcycle"\n{\n\t"Normal"\n\t{\n\t\t"de_dust2"\n\t\t{\n\t\t}\n\t}\n}\n'
        )
        self.sandbox_file.write_text(initial_content, encoding="utf-8")

        self.data = parse_umc_file(self.sandbox_file)

    def tearDown(self):
        """Clean up the sandbox after each test run."""
        if self.sandbox_file.exists():
            self.sandbox_file.unlink()
        if self.results_dir.exists() and not any(self.results_dir.iterdir()):
            self.results_dir.rmdir()

    def test_category_already_exists(self):
        """Check to make sure that an existing category cannot be recreated."""
        with self.assertRaises(CategoryAlreadyExists):
            add_category(self.data, "Normal")

    def test_map_already_exists(self):
        """Check to make sure that an existing map cannot be added to a category."""
        with self.assertRaises(MapAlreadyExists):
            add_map_to_category(self.data, "Normal", "de_dust2")

    def test_invalid_map_name(self):
        """Check that a map containing spaces or a prohibited name raises a ValidationError."""
        with self.assertRaises(ValidationError):
            add_map_to_category(self.data, "Normal", "de dust2")

    def test_invalid_option(self):
        """Verify that an option not listed (e.g., "banana") is rejected by the validator."""
        with self.assertRaises(ValidationError):
            add_map_to_category(self.data, "Normal", "de_test_option", {"banana": "42"})

    def test_invalid_type(self):
        """Verify that a value that is not of the expected type (e.g., 'abc' instead of a digit for 'tier') triggers an error."""
        with self.assertRaises(ValidationError):
            add_map_to_category(self.data, "Normal", "de_test_type", {"tier": "abc"})

    def test_min_players_greater_than_max_players(self):
        """Check that the logic prevents insertion if min_players > max_players."""
        with self.assertRaises(ValidationError):
            add_map_to_category(
                self.data, "Normal", "de_test_limits", {"min_players": "20", "max_players": "10"}
            )


if __name__ == "__main__":
    unittest.main()
