import tempfile
import unittest
from pathlib import Path

from gnos.core.attest import AttestationError, attest_manifest_bytes
from gnos.core.hash import sha256_hex
from gnos.core.store import ObjectStore
from gnos.manifest.codec import dump_manifest_bytes
from gnos.manifest.schema import DocManifest


class TestAttestErrors(unittest.TestCase):
    def test_wrong_doc_id(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            store = ObjectStore(Path(tmp))
            store.init()
            chunk = b"hello\n"
            h = sha256_hex(chunk)
            store.put(h, chunk)

            manifest = DocManifest(
                type="doc-manifest",
                version=1,
                doc_id="0" * 64,
                format="markdown",
                chunking={"method": "sequential-v1", "params": {"chunk_size": 1024}},
                chunks=[{"hash": h}],
            )
            manifest_bytes = dump_manifest_bytes(manifest)
            with self.assertRaises(AttestationError):
                attest_manifest_bytes(manifest_bytes, store, expected_doc_id=h)

    def test_manifest_hash_mismatch(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            store = ObjectStore(Path(tmp))
            store.init()
            chunk = b"hello\n"
            h = sha256_hex(chunk)
            store.put(h, chunk)

            manifest = DocManifest(
                type="doc-manifest",
                version=1,
                doc_id=sha256_hex(chunk),
                format="markdown",
                chunking={"method": "sequential-v1", "params": {"chunk_size": 1024}},
                chunks=[{"hash": h}],
            )
            manifest_bytes = dump_manifest_bytes(manifest)
            with self.assertRaises(AttestationError):
                attest_manifest_bytes(
                    manifest_bytes,
                    store,
                    expected_manifest_hash="f" * 64,
                )

    def test_chunk_hash_mismatch(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            store = ObjectStore(Path(tmp))
            store.init()
            chunk = b"hello\n"
            bad_hash = "1" * 64
            store.put(bad_hash, chunk)

            manifest = DocManifest(
                type="doc-manifest",
                version=1,
                doc_id=sha256_hex(chunk),
                format="markdown",
                chunking={"method": "sequential-v1", "params": {"chunk_size": 1024}},
                chunks=[{"hash": bad_hash}],
            )
            manifest_bytes = dump_manifest_bytes(manifest)
            with self.assertRaises(AttestationError):
                attest_manifest_bytes(manifest_bytes, store)


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