import tempfile
import unittest
from pathlib import Path

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


class TestAttest(unittest.TestCase):
    def test_attest_file_to_doc_id_with_newlines(self) -> None:
        data = b"line1\r\nline2\r\n"
        doc_id = sha256_hex(data)
        result = attest_file_to_doc_id(data, doc_id)
        self.assertTrue(result.ok)
        self.assertEqual(result.doc_id, doc_id)

    def test_attest_manifest_success(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            store = ObjectStore(Path(tmp))
            store.init()

            doc_bytes = b"hello\nworld\n"
            chunk1 = b"hello\n"
            chunk2 = b"world\n"

            h1 = sha256_hex(chunk1)
            h2 = sha256_hex(chunk2)
            doc_id = sha256_hex(doc_bytes)

            store.put(h1, chunk1)
            store.put(h2, chunk2)

            manifest = DocManifest(
                type="doc-manifest",
                version=1,
                doc_id=doc_id,
                format="markdown",
                chunking={"method": "sequential-v1", "params": {"chunk_size": 1024}},
                chunks=[{"hash": h1}, {"hash": h2}],
            )
            manifest_bytes = dump_manifest_bytes(manifest)
            manifest_hash = sha256_hex(manifest_bytes)

            result = attest_manifest_bytes(
                manifest_bytes,
                store,
                expected_doc_id=doc_id,
                expected_manifest_hash=manifest_hash,
            )
            self.assertTrue(result.ok)

    def test_attest_manifest_missing_chunk(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            store = ObjectStore(Path(tmp))
            store.init()

            chunk1 = b"hello\n"
            h1 = sha256_hex(chunk1)
            h2 = "0" * 64
            doc_id = sha256_hex(chunk1)

            store.put(h1, chunk1)

            manifest = DocManifest(
                type="doc-manifest",
                version=1,
                doc_id=doc_id,
                format="markdown",
                chunking={"method": "sequential-v1", "params": {"chunk_size": 1024}},
                chunks=[{"hash": h1}, {"hash": h2}],
            )
            manifest_bytes = dump_manifest_bytes(manifest)

            with self.assertRaises(AttestationError):
                attest_manifest_bytes(manifest_bytes, store, expected_doc_id=doc_id)


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