import hashlib
import json
import sys
import tempfile
import unittest
from pathlib import Path

PACKAGE_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(PACKAGE_ROOT / "dependencies"))

from verify_runtime_data import RuntimeDataError, verify_runtime_data  # noqa: E402


class VerifyRuntimeDataTest(unittest.TestCase):
    def setUp(self):
        self.temp_dir = tempfile.TemporaryDirectory()
        self.root = Path(self.temp_dir.name)
        self.model_dir = self.root / "models" / "en_zh-Hans"
        self.model_dir.mkdir(parents=True)
        self.records_path = self.root / "records.json"

    def tearDown(self):
        self.temp_dir.cleanup()

    def write_fixture(self):
        records = []
        fixtures = {
            "model": ("model.bin", b"model"),
            "lex": ("lex.bin", b"lex"),
            "srcvocab": ("src.spm", b"source"),
            "trgvocab": ("trg.spm", b"target"),
        }
        for role, (filename, content) in fixtures.items():
            (self.model_dir / filename).write_bytes(content)
            records.append(
                {
                    "sourceLanguage": "en",
                    "targetLanguage": "zh-Hans",
                    "fileType": role,
                    "version": "1.0",
                    "decompressedHash": hashlib.sha256(content).hexdigest(),
                    "decompressedSize": len(content),
                    "attachment": {"filename": f"{filename}.zst"},
                }
            )
        self.records_path.write_text(json.dumps({"data": records}))
        return fixtures

    def test_accepts_exact_four_verified_files(self):
        fixtures = self.write_fixture()

        selected = verify_runtime_data(self.records_path, self.model_dir)

        self.assertEqual(set(selected), set(fixtures))
        self.assertEqual(selected["model"].name, "model.bin")

    def test_rejects_hash_mismatch(self):
        self.write_fixture()
        (self.model_dir / "model.bin").write_bytes(b"other")

        with self.assertRaisesRegex(RuntimeDataError, "hash mismatch"):
            verify_runtime_data(self.records_path, self.model_dir)

    def test_rejects_missing_required_role(self):
        self.write_fixture()
        records = json.loads(self.records_path.read_text())
        records["data"] = [item for item in records["data"] if item["fileType"] != "lex"]
        self.records_path.write_text(json.dumps(records))

        with self.assertRaisesRegex(RuntimeDataError, "missing required record role: lex"):
            verify_runtime_data(self.records_path, self.model_dir)

    def test_rejects_unselected_model_file(self):
        self.write_fixture()
        (self.model_dir / "unexpected.bin").write_bytes(b"extra")

        with self.assertRaisesRegex(RuntimeDataError, "unexpected model files"):
            verify_runtime_data(self.records_path, self.model_dir)


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