#!/usr/bin/env python3
from __future__ import annotations

import json
import shutil
import tempfile
import unittest
from pathlib import Path

import version_server


class VersionStoreTests(unittest.TestCase):
    def setUp(self) -> None:
        self.tmp = Path(tempfile.mkdtemp(prefix="dpe-version-test-"))
        self.store = version_server.VersionStore(self.tmp)

    def tearDown(self) -> None:
        shutil.rmtree(self.tmp)

    def test_saves_project_versions_separately_and_marks_latest_current(self) -> None:
        first = self.store.save_version("project-a", "<html>A1</html>", title="A one", note="first")
        second = self.store.save_version("project-b", "<html>B1</html>", title="B one")
        third = self.store.save_version("project-a", "<html>A2</html>", title="A two")

        self.assertNotEqual(first["version_id"], third["version_id"])
        self.assertEqual(self.store.get_current("project-a")["html"], "<html>A2</html>")
        self.assertEqual(self.store.get_current("project-b")["html"], "<html>B1</html>")
        self.assertEqual(self.store.get_manifest("project-a")["current_version_id"], third["version_id"])
        self.assertEqual(len(self.store.list_versions("project-a")["versions"]), 2)
        self.assertEqual(len(self.store.list_versions("project-b")["versions"]), 1)

    def test_rejects_unsafe_project_ids(self) -> None:
        with self.assertRaises(ValueError):
            self.store.save_version("../bad", "<html></html>")

    def test_set_current_switches_without_copying_other_projects(self) -> None:
        a1 = self.store.save_version("project-a", "<html>A1</html>")
        self.store.save_version("project-a", "<html>A2</html>")
        self.store.save_version("project-b", "<html>B1</html>")
        switched = self.store.set_current("project-a", a1["version_id"])
        self.assertEqual(switched["current_version_id"], a1["version_id"])
        self.assertEqual(self.store.get_current("project-a")["html"], "<html>A1</html>")
        self.assertEqual(self.store.get_current("project-b")["html"], "<html>B1</html>")

    def test_auto_prunes_to_latest_20_versions_and_removes_files(self) -> None:
        saved = [self.store.save_version("project-a", f"<html>A{i}</html>") for i in range(25)]
        manifest = self.store.list_versions("project-a")
        version_ids = [v["version_id"] for v in manifest["versions"]]

        self.assertEqual(len(version_ids), 20)
        self.assertEqual(manifest["current_version_id"], saved[-1]["version_id"])
        self.assertEqual(version_ids[0], saved[-1]["version_id"])
        self.assertNotIn(saved[0]["version_id"], version_ids)
        self.assertFalse((self.tmp / "projects" / "project-a" / "versions" / f"{saved[0]['version_id']}.html").exists())
        self.assertFalse((self.tmp / "projects" / "project-a" / "versions" / f"{saved[0]['version_id']}.json").exists())


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