"""Tests for core.services.mapcycle_service.get_mod_target_category."""

import json
import sys
import tempfile
import unittest
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 import constants
from core.services.mapcycle_service import get_mod_target_category


class TestGetModTargetCategory(unittest.TestCase):
    def setUp(self) -> None:
        self.sandbox = tempfile.TemporaryDirectory()
        self.sandbox_path = Path(self.sandbox.name)
        constants.REPOSITORY = self.sandbox_path / "repository"
        constants.REPOSITORY.mkdir(parents=True, exist_ok=True)

    def tearDown(self) -> None:
        self.sandbox.cleanup()

    def _make_mod(self, mod_id: str, manifest: dict | None) -> None:
        mod_dir = constants.REPOSITORY / mod_id
        mod_dir.mkdir(parents=True, exist_ok=True)
        if manifest is not None:
            with (mod_dir / "manifest.json").open("w", encoding="utf-8") as f:
                json.dump(manifest, f)

    def test_returns_none_when_manifest_missing(self) -> None:
        self._make_mod("no_manifest", manifest=None)
        self.assertIsNone(get_mod_target_category("no_manifest"))

    def test_returns_none_when_mod_folder_missing(self) -> None:
        self.assertIsNone(get_mod_target_category("ghost"))

    def test_returns_none_when_no_target_category_set(self) -> None:
        self._make_mod("no_target", {"id": "no_target"})
        self.assertIsNone(get_mod_target_category("no_target"))

    def test_returns_not_shared_when_alone(self) -> None:
        self._make_mod("solo", {"id": "solo", "target_category": "Normal"})

        result = get_mod_target_category("solo")

        self.assertEqual(result, {"category": "Normal", "shared": False})

    def test_returns_shared_when_another_mod_uses_same_category(self) -> None:
        self._make_mod("mod_a", {"id": "mod_a", "target_category": "Aim"})
        self._make_mod("mod_b", {"id": "mod_b", "target_category": "Aim"})

        result = get_mod_target_category("mod_a")

        self.assertEqual(result, {"category": "Aim", "shared": True})

    def test_category_comparison_is_case_and_whitespace_insensitive(self) -> None:
        self._make_mod("mod_a", {"id": "mod_a", "target_category": "Aim"})
        self._make_mod("mod_b", {"id": "mod_b", "target_category": "  aim  "})

        result = get_mod_target_category("mod_a")

        self.assertTrue(result["shared"])

    def test_ignores_other_mods_with_different_category(self) -> None:
        self._make_mod("mod_a", {"id": "mod_a", "target_category": "Aim"})
        self._make_mod("mod_b", {"id": "mod_b", "target_category": "Surf"})

        result = get_mod_target_category("mod_a")

        self.assertFalse(result["shared"])

    def test_skips_unreadable_manifest_of_another_mod_without_crashing(self) -> None:
        """Regression test: the original code caught `CoreError`, which does not
        cover json.JSONDecodeError/OSError, so a single malformed manifest in
        the repository would crash the lookup for every other mod.
        """
        self._make_mod("mod_a", {"id": "mod_a", "target_category": "Aim"})
        broken_dir = constants.REPOSITORY / "mod_broken"
        broken_dir.mkdir(parents=True, exist_ok=True)
        (broken_dir / "manifest.json").write_text("{not valid json", encoding="utf-8")

        result = get_mod_target_category("mod_a")  # should not raise

        self.assertEqual(result, {"category": "Aim", "shared": False})


if __name__ == "__main__":
    unittest.main()
