import importlib.util
import json
from pathlib import Path
import tempfile
import unittest


SCRIPT = Path(__file__).parents[1] / "scripts" / "manifest_preflight.py"
SPEC = importlib.util.spec_from_file_location("manifest_preflight", SCRIPT)
assert SPEC and SPEC.loader
MODULE = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(MODULE)


class ManifestPreflightTests(unittest.TestCase):
    def write_manifest(self, root: Path, data: object) -> Path:
        path = root / "manifest.webmanifest"
        path.write_text(json.dumps(data), encoding="utf-8")
        return path

    def test_complete_manifest_has_no_findings(self):
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)
            (root / "icon-192.png").touch()
            (root / "icon-512.png").touch()
            manifest = self.write_manifest(
                root,
                {
                    "id": "/app",
                    "name": "Example App",
                    "short_name": "Example",
                    "start_url": "/app/",
                    "scope": "/app/",
                    "display": "standalone",
                    "theme_color": "#112233",
                    "background_color": "#ffffff",
                    "icons": [
                        {"src": "icon-192.png", "sizes": "192x192", "type": "image/png"},
                        {"src": "icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable"},
                    ],
                },
            )
            self.assertEqual(MODULE.review(manifest), [])

    def test_missing_required_members_are_errors(self):
        with tempfile.TemporaryDirectory() as directory:
            manifest = self.write_manifest(Path(directory), {})
            findings = MODULE.review(manifest)
            codes = {item["code"] for item in findings if item["level"] == "error"}
            self.assertEqual(codes, {"name-missing", "start-url-missing", "icons-missing"})

    def test_start_url_outside_scope_is_reported(self):
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)
            (root / "icon.png").touch()
            manifest = self.write_manifest(
                root,
                {
                    "id": "/app",
                    "name": "Example",
                    "start_url": "/outside/",
                    "scope": "/app/",
                    "display": "standalone",
                    "theme_color": "#000000",
                    "background_color": "#ffffff",
                    "icons": [{"src": "icon.png", "sizes": "any", "purpose": "maskable"}],
                },
            )
            self.assertIn("scope-start-url", {item["code"] for item in MODULE.review(manifest)})


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