"""Performance regression guards.

These tests run in every CI build (NO special marker). They use generous
thresholds (5-10x headroom) to catch catastrophic regressions, not 5%
changes.  For precise measurement, use ``scripts/benchmark.py``.
"""

from __future__ import annotations

import time
from pathlib import Path

from certisigma import hash_file

from certisigma_census.manifest import Manifest, ManifestEntry


class TestHashPerformance:

    def test_hash_10k_small_files(self, tmp_path: Path):
        """Hashing 10 000 x 1 KB files should complete in < 30 s."""
        for i in range(10_000):
            (tmp_path / f"f_{i:05d}.bin").write_bytes(b"\x00" * 1024)

        t0 = time.perf_counter()
        for p in tmp_path.iterdir():
            hash_file(str(p))
        elapsed = time.perf_counter() - t0

        assert elapsed < 30, f"Hashing 10K files took {elapsed:.1f}s (limit: 30s)"


class TestManifestPerformance:

    def test_manifest_10k_inserts(self):
        """10 000 manifest.add() calls should complete in < 10 s."""
        m = Manifest(root_dir="/perf")
        try:
            t0 = time.perf_counter()
            for i in range(10_000):
                m.add(ManifestEntry(
                    hash_hex=f"{i:064x}", path=f"f_{i}.bin",
                    size=1024, mtime=float(i),
                ))
            elapsed = time.perf_counter() - t0
        finally:
            m.close()

        assert elapsed < 10, f"10K inserts took {elapsed:.1f}s (limit: 10s)"

    def test_manifest_save_load_10k(self, tmp_path: Path):
        """Save + load round-trip for 10 000 entries should complete in < 5 s."""
        m = Manifest(root_dir="/perf")
        try:
            for i in range(10_000):
                m.add(ManifestEntry(
                    hash_hex=f"{i:064x}", path=f"f_{i}.bin",
                    size=1024, mtime=float(i),
                ))
            db = tmp_path / "perf.db"

            t0 = time.perf_counter()
            m.save(db)
        finally:
            m.close()

        loaded = Manifest.load(db)
        elapsed = time.perf_counter() - t0
        try:
            assert loaded.total == 10_000
        finally:
            loaded.close()

        assert elapsed < 5, f"Save+load took {elapsed:.1f}s (limit: 5s)"
