import tempfile
import unittest
from pathlib import Path

from gnos.core.materialize import materialize_doc_id, materialize_collection, MaterializeError
from gnos.core.store import ObjectStore
from gnos.index.local import LocalIndex
from gnos.manifest.schema import DocManifest, CollectionManifest, CollectionEntry
from gnos.manifest.codec import dump_manifest_bytes, dump_collection_bytes
from gnos.core.hash import sha256_hex, canonicalize_bytes


class TestMaterializeErrors(unittest.TestCase):
    def test_materialize_doc_missing_index(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            store = ObjectStore(root / ".gnos")
            store.init()
            index = LocalIndex(root / ".gnos" / "index.json")
            with self.assertRaises(MaterializeError):
                materialize_doc_id("0" * 64, store, index, root / "out.md")

    def test_materialize_doc_missing_chunk(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            store = ObjectStore(root / ".gnos")
            store.init()
            index = LocalIndex(root / ".gnos" / "index.json")

            content = b"hello\n"
            doc_id = sha256_hex(canonicalize_bytes(content))
            chunk_hash = sha256_hex(content)

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

            index.record_manifest(
                doc_id,
                manifest_hash,
                "markdown",
                {"method": "sequential-v1", "params": {"chunk_size": 1024}},
                [{"hash": chunk_hash}],
            )

            with self.assertRaises(MaterializeError):
                materialize_doc_id(doc_id, store, index, root / "out.md")

    def test_materialize_collection_missing_path(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            store = ObjectStore(root / ".gnos")
            store.init()
            index = LocalIndex(root / ".gnos" / "index.json")

            doc_id = "a" * 64
            collection = CollectionManifest(
                type="collection-manifest",
                version=1,
                documents=[CollectionEntry(doc_id=doc_id, path=None)],
            )
            blob = dump_collection_bytes(collection)
            collection_id = sha256_hex(blob)
            store.put(collection_id, blob)

            with self.assertRaises(MaterializeError):
                materialize_collection(collection_id, store, index, root / "out")


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