from __future__ import annotations

import json
from pathlib import Path

from rdflib import Dataset

from cf_ontology.namespaces import CF_BASE
from cf_ontology.pipeline_id import derive_pipeline_id_from_document
from cf_ontology.quad_store import QuadStore

_STRUCTURED_FORMAT = "json" + "-ld"


def _pipeline_doc() -> dict:
    return {
        "@context": {
            "cf": CF_BASE,
            "ex": "http://example.org/",
        },
        "@graph": [
            {
                "@id": "ex:pipe-a",
                "@type": "cf:ProcessingPipeline",
                "cf:hasPipelineNode": {"@id": "ex:n1"},
            },
            {
                "@id": "ex:n1",
                "@type": "cf:PipelineNode",
                "cf:hasParameterBinding": {"@id": "ex:n1_endpoint_binding"},
            },
            {
                "@id": "ex:n1_endpoint_binding",
                "@type": "cf:ParameterBinding",
                "cf:bindsParameter": {"@id": "ex:InputStep_param_endpoint"},
                "cf:value": "opc.tcp://127.0.0.1:4840/VirtualPhServer",
            },
        ],
    }


def _write_nquads(path: Path, document: dict) -> Path:
    dataset = Dataset()
    dataset.parse(data=json.dumps(document), format=_STRUCTURED_FORMAT)
    payload = dataset.serialize(format="nquads")
    if isinstance(payload, bytes):
        payload = payload.decode("utf-8")
    path.write_text(payload, encoding="utf-8")
    return path


def test_derive_pipeline_id_from_nquads_document(tmp_path: Path) -> None:
    path = _write_nquads(tmp_path / "pipeline.nq", _pipeline_doc())

    assert derive_pipeline_id_from_document(path) == "pipe-a"


def test_commit_pipeline_revision_accepts_nquads_document(tmp_path: Path) -> None:
    semantics_dir = tmp_path / "semantics"
    store = QuadStore(
        db_path=semantics_dir / "cf-pipelines.duckdb",
        semantics_dir=semantics_dir,
    )
    store.init_schema(create_pipeline_tables=True)
    path = _write_nquads(tmp_path / "pipeline.nq", _pipeline_doc())

    rev = store.commit_pipeline_revision("pipe-a", path, created_by="alice", message="nq")

    assert rev == 1
    exported = store.load_pipeline_revision_nquads("pipe-a", rev)
    assert "https://cogniflow.odea-project.org/cf#ProcessingPipeline" in exported
    assert "opc.tcp://127.0.0.1:4840/VirtualPhServer" in exported