"""hub_backup_lib 单元测试."""
from __future__ import annotations

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

ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))

from lib.hub import hub_backup_lib as backup


class HubBackupLibTest(unittest.TestCase):
    def test_normalize_backup_settings(self):
        cfg = backup.normalize_backup_settings({"auto_hour": 99, "retention_days": 0})
        self.assertEqual(cfg["auto_hour"], 23)
        self.assertEqual(cfg["retention_days"], 1)

    def test_safe_archive_name(self):
        self.assertTrue(backup._safe_archive_name("backup_2026-07-02_163045.zip"))
        self.assertFalse(backup._safe_archive_name("../evil.zip"))

    def test_run_and_restore_roundtrip(self):
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp) / "portal"
            root.mkdir(parents=True)
            settings = {
                "backup": {
                    "auto_enabled": False,
                    "backup_root": str(root),
                    "include_env": False,
                    "include_exchange_images": False,
                }
            }
            hub_settings = backup.HUB_DIR / "hub_settings.json"
            had = hub_settings.is_file()
            old = hub_settings.read_text(encoding="utf-8") if had else None
            try:
                if not had:
                    hub_settings.write_text('{"version":1,"exchanges":[]}', encoding="utf-8")
                result = backup.run_backup(trigger="manual", settings=settings)
                self.assertTrue(result.get("ok"), result)
                archive = Path(result["path"])
                self.assertTrue(archive.is_file())
                with zipfile.ZipFile(archive, "r") as zf:
                    names = zf.namelist()
                self.assertIn("manifest.json", names)
                manifest = json.loads(
                    zipfile.ZipFile(archive, "r").read("manifest.json").decode("utf-8")
                )
                self.assertEqual(manifest.get("trigger"), "manual")
            finally:
                if had and old is not None:
                    hub_settings.write_text(old, encoding="utf-8")
                elif not had and hub_settings.is_file():
                    hub_settings.unlink(missing_ok=True)


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