from __future__ import annotations

import json
from pathlib import Path

import duckdb
from rdflib import Dataset

from cf_ontology import ingest_rdf_documents
from cf_ontology.rdf_document import load_rdf_document
from cf_ontology.semantics_paths import resolve_semantics_db_path
from cf_ontology.signature import generate_signature_header

_STRUCTURED_FORMAT = "json" + "-ld"


def _repo_root() -> Path:
    return Path(__file__).resolve().parents[3]


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 _basic_signal_steps_document() -> dict:
    source = (
        _repo_root()
        / "sandcastle"
        / "cf_basic_steps"
        / "cf_basic_signal"
        / "src"
        / "cf_basic_signal"
        / "steps.nq"
    )
    return load_rdf_document(source, label="step document")


def test_nquads_step_document_ingest_stores_expected_graph_ids(tmp_path: Path) -> None:
    document = _basic_signal_steps_document()
    nq_path = _write_nquads(tmp_path / "basic_signal_steps.nq", document)
    semantics_dir = tmp_path / "semantics"

    ingest_rdf_documents(
        [nq_path],
        semantics_dir=semantics_dir,
        graph_type="step",
        package="cf.basic.signal",
    )

    db_path = resolve_semantics_db_path(semantics_dir, kind="steps")
    con = duckdb.connect(str(db_path), read_only=True)
    try:
        rows = con.execute("SELECT graph_id FROM graphs ORDER BY graph_id").fetchall()
    finally:
        con.close()

    graph_ids = {str(row[0]) for row in rows}
    assert any(graph_id.endswith("basic-signal/AverageStep") for graph_id in graph_ids)
    assert any(graph_id.endswith("basic-signal/FifoWindowBufferStep") for graph_id in graph_ids)


def test_siggen_accepts_nquads_step_document(tmp_path: Path) -> None:
    document = _basic_signal_steps_document()
    nq_path = _write_nquads(tmp_path / "basic_signal_steps.nq", document)
    out_path = tmp_path / "signatures.hpp"

    signatures = generate_signature_header(
        documents=[nq_path],
        out_path=out_path,
        scratch=True,
    )

    assert signatures
    assert any(signature.step_iri.endswith("AverageStep") for signature in signatures)
    header = out_path.read_text(encoding="utf-8")
    assert "AverageStep" in header