"""RDF / JSON-LD / SHACL API routes for ontology export, import, and validation."""

from __future__ import annotations

from typing import Any

from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import PlainTextResponse

from pycharter.wiki.api.dependencies import get_db_session
from pycharter.wiki.shared.errors import OntologyError

router = APIRouter(tags=["Wiki"])


# ── Concept export ───────────────────────────────────────────────────────────


@router.get("/concepts/export")
async def export_concepts(
    format: str = Query("jsonld", pattern="^(jsonld|ttl)$"),
    session=Depends(get_db_session),
):
    """Export the full concept scheme as JSON-LD or Turtle."""
    try:
        from pycharter.db.models.wiki.concept import ConceptModel
        from pycharter.wiki.ontology.models import ConceptDefinition, ConceptScheme
        from pycharter.wiki.rdf.emitter import emit_concepts_jsonld

        rows = session.query(ConceptModel).order_by(ConceptModel.name).all()
        name_to_id: dict[str, Any] = {r.name: r.id for r in rows}
        id_to_name: dict[Any, str] = {r.id: r.name for r in rows}

        concepts = []
        for r in rows:
            broader = id_to_name.get(r.parent_id) if r.parent_id else None
            concepts.append(
                ConceptDefinition(
                    id=r.name,
                    label=r.name,
                    definition=r.description,
                    broader=broader,
                    notation=r.notation,
                    deprecated=r.deprecated or False,
                )
            )

        scheme = ConceptScheme(
            id="StatFYIExport",
            title="StatFYI Concept Export",
            version="1.0.0",
            concepts=concepts,
        )

        doc = emit_concepts_jsonld(scheme)

        if format == "ttl":
            from pycharter.wiki.rdf.converter import jsonld_to_ttl

            return PlainTextResponse(jsonld_to_ttl(doc), media_type="text/turtle")

        return doc

    except ImportError:
        raise HTTPException(
            status_code=501,
            detail="RDF support requires the 'ontology' extra: pip install pycharter[ontology]",
        )


# ── Ontology export ──────────────────────────────────────────────────────────


@router.get("/ontology/{contract_id}/export")
async def export_ontology(
    contract_id: str,
    format: str = Query("jsonld", pattern="^(jsonld|ttl)$"),
    session=Depends(get_db_session),
):
    """Export a contract's ontology (field mappings) as JSON-LD or Turtle."""
    try:
        from pycharter.db.models.wiki.contract_version import ContractVersionModel
        from pycharter.wiki.ontology.parser import parse_ontology
        from pycharter.wiki.rdf.emitter import emit_ontology_jsonld

        version = (
            session.query(ContractVersionModel)
            .filter(ContractVersionModel.contract_id == contract_id)
            .order_by(ContractVersionModel.created_at.desc())
            .first()
        )
        if version is None:
            raise HTTPException(
                status_code=404, detail=f"No ontology found for {contract_id}"
            )

        artifact = parse_ontology(version.content)
        doc = emit_ontology_jsonld(artifact, contract_id)

        if format == "ttl":
            from pycharter.wiki.rdf.converter import jsonld_to_ttl

            return PlainTextResponse(jsonld_to_ttl(doc), media_type="text/turtle")

        return doc

    except ImportError:
        raise HTTPException(
            status_code=501,
            detail="RDF support requires the 'ontology' extra: pip install pycharter[ontology]",
        )


# ── SHACL validation ─────────────────────────────────────────────────────────


@router.post("/ontology/{contract_id}/validate-shacl")
async def validate_shacl_endpoint(
    contract_id: str,
    session=Depends(get_db_session),
):
    """Run SHACL validation on a contract's ontology and return a report."""
    try:
        from pycharter.db.models.wiki.contract_version import ContractVersionModel
        from pycharter.wiki.ontology.parser import parse_ontology
        from pycharter.wiki.rdf.shacl_validator import validate_ontology_shacl

        version = (
            session.query(ContractVersionModel)
            .filter(ContractVersionModel.contract_id == contract_id)
            .order_by(ContractVersionModel.created_at.desc())
            .first()
        )
        if version is None:
            raise HTTPException(
                status_code=404, detail=f"No ontology found for {contract_id}"
            )

        artifact = parse_ontology(version.content)
        report = validate_ontology_shacl(artifact, contract_id)

        return {
            "conforms": report.conforms,
            "violations": report.violations,
            "raw_text": report.raw_text,
        }

    except ImportError:
        raise HTTPException(
            status_code=501,
            detail="SHACL support requires the 'ontology' extra: pip install pycharter[ontology]",
        )


# ── JSON-LD import ───────────────────────────────────────────────────────────


@router.post("/ontology/import-jsonld")
async def import_ontology_jsonld(
    payload: dict[str, Any],
    contract_id: str = Query(...),
    author: str = Query("api"),
    session=Depends(get_db_session),
):
    """Import a field-mapping ontology from a JSON-LD payload."""
    try:
        from pycharter.wiki.rdf.jsonld_parser import parse_ontology_jsonld

        artifact = parse_ontology_jsonld(payload)

        from pycharter.wiki.ingestion.importer import OntologyImporter

        importer = OntologyImporter(session=session)
        result = importer._materialize(
            contract_id=contract_id,
            artifact_dict=artifact.to_dict(),
            field_types={},
            author=author,
        )
        session.commit()
        return result

    except OntologyError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except ImportError:
        raise HTTPException(
            status_code=501,
            detail="JSON-LD support requires the 'ontology' extra: pip install pycharter[ontology]",
        )


# ── Concept import ───────────────────────────────────────────────────────────


@router.post("/concepts/import")
async def import_concepts(
    payload: dict[str, Any],
    author: str = Query("api"),
    session=Depends(get_db_session),
):
    """Import a concept scheme from a JSON-LD payload."""
    try:
        from pycharter.wiki.rdf.jsonld_parser import parse_concepts_jsonld
        from pycharter.wiki.rdf.vocabulary import ingest_vocabulary

        scheme = parse_concepts_jsonld(payload)
        result = ingest_vocabulary(scheme, session, author=author)
        return result

    except OntologyError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except ImportError:
        raise HTTPException(
            status_code=501,
            detail="JSON-LD support requires the 'ontology' extra: pip install pycharter[ontology]",
        )


# ── Concept CRUD ─────────────────────────────────────────────────────────────


@router.get("/concepts/{name}")
async def get_concept(name: str, session=Depends(get_db_session)):
    """Get a concept by name."""
    from pycharter.wiki.ontology.concept_manager import ConceptManager

    mgr = ConceptManager(session)
    concept = mgr.get(name)
    if concept is None:
        raise HTTPException(status_code=404, detail=f"Concept not found: {name}")
    return concept


@router.post("/concepts")
async def create_concept(
    payload: dict[str, Any],
    author: str = Query("api"),
    session=Depends(get_db_session),
):
    """Create a new concept."""
    from pycharter.wiki.ontology.concept_manager import ConceptManager
    from pycharter.wiki.ontology.models import ConceptDefinition

    try:
        concept = ConceptDefinition(
            id=payload["id"],
            label=payload.get("label", payload["id"]),
            definition=payload.get("definition"),
            broader=payload.get("broader"),
            tags=payload.get("tags", []),
            notation=payload.get("notation"),
            deprecated=payload.get("deprecated", False),
        )
        mgr = ConceptManager(session)
        return mgr.create(concept, author=author)
    except KeyError as e:
        raise HTTPException(status_code=400, detail=f"Missing required field: {e}")
    except OntologyError as e:
        raise HTTPException(status_code=409, detail=str(e))


@router.put("/concepts/{name}")
async def update_concept(
    name: str,
    payload: dict[str, Any],
    author: str = Query("api"),
    session=Depends(get_db_session),
):
    """Update a concept."""
    from pycharter.wiki.ontology.concept_manager import ConceptManager

    try:
        mgr = ConceptManager(session)
        return mgr.update(name, payload, author=author)
    except OntologyError as e:
        raise HTTPException(status_code=404, detail=str(e))


@router.delete("/concepts/{name}")
async def delete_concept(name: str, session=Depends(get_db_session)):
    """Delete a concept by name."""
    from pycharter.wiki.ontology.concept_manager import ConceptManager

    mgr = ConceptManager(session)
    if not mgr.delete(name):
        raise HTTPException(status_code=404, detail=f"Concept not found: {name}")
    return {"deleted": True}
