from __future__ import annotations

from hashlib import sha256

from app.core.rag.contracts import EvidenceLink, EvidenceType, RagDocument, RagLayer, RagSource
from app.core.rag.indexing.docs.frontmatter_view import DocsFrontmatterView
from app.core.rag.indexing.docs.models import IntegrationRecord, RelationEdge, WorkflowScenario


class DocsSupportLayerBuilder:
    def build_fact(
        self,
        source: RagSource,
        *,
        subject_id: str,
        predicate: str,
        obj: str,
        object_ref: str | None,
        anchor: str,
        tags: list[str] | None = None,
        domain: str = "",
        subdomain: str = "",
    ) -> RagDocument:
        fact_id = sha256(f"{subject_id}|{predicate}|{obj}|{source.path}|{anchor}".encode("utf-8")).hexdigest()
        metadata = {
            "fact_id": fact_id,
            "subject_id": subject_id,
            "predicate": predicate,
            "object": obj,
            "object_ref": object_ref,
            "anchor": anchor,
            "tags": tags or [],
            "domain": domain,
            "subdomain": subdomain,
            "source_path": source.path,
            "artifact_type": "DOCS",
        }
        return RagDocument(
            layer=RagLayer.DOCS_FACT_INDEX,
            source=source,
            title=f"{subject_id}:{predicate}",
            text=f"{subject_id} {predicate} {obj}".strip(),
            metadata=metadata,
            links=[EvidenceLink(type=EvidenceType.DOC_FACT, target_id=fact_id, path=source.path, note=anchor)],
        )

    def build_workflow_record(self, source: RagSource, frontmatter: dict, workflow: WorkflowScenario) -> RagDocument:
        view = DocsFrontmatterView(frontmatter)
        document_id = view.document_id or source.path
        workflow_id = sha256(f"{document_id}|workflow|{workflow.name}|{workflow.anchor}".encode("utf-8")).hexdigest()
        metadata = {
            "workflow_id": workflow_id,
            "document_id": document_id,
            "workflow_name": workflow.name,
            "preconditions": workflow.preconditions,
            "trigger": workflow.trigger,
            "main_flow": workflow.main_flow,
            "alternative_flow": workflow.alternative_flow,
            "error_handling": workflow.error_handling,
            "postconditions": workflow.postconditions,
            "domain": view.domain,
            "subdomain": view.subdomain,
            "source_path": source.path,
            "artifact_type": "DOCS",
        }
        text = "\n".join(
            [
                workflow.name,
                *workflow.preconditions,
                *workflow.trigger,
                *workflow.main_flow,
                *workflow.alternative_flow,
                *workflow.error_handling,
                *workflow.postconditions,
            ]
        ).strip()
        return RagDocument(
            layer=RagLayer.DOCS_WORKFLOW_INDEX,
            source=source,
            title=workflow.name,
            text=text[:4000],
            metadata=metadata,
        )

    def build_relation_record(self, source: RagSource, frontmatter: dict, edge: RelationEdge) -> RagDocument:
        view = DocsFrontmatterView(frontmatter)
        relation_id = sha256(f"{edge.source_id}|{edge.relation_type}|{edge.target_id}|{source.path}|{edge.anchor}".encode("utf-8")).hexdigest()
        metadata = {
            "relation_id": relation_id,
            "source_id": edge.source_id,
            "relation_type": edge.relation_type,
            "target_id": edge.target_id,
            "anchor": edge.anchor,
            "domain": view.domain,
            "subdomain": view.subdomain,
            "source_path": source.path,
            "artifact_type": "DOCS",
        }
        return RagDocument(
            layer=RagLayer.DOCS_RELATION_GRAPH,
            source=source,
            title=f"{edge.source_id}:{edge.relation_type}",
            text=f"{edge.source_id} {edge.relation_type} {edge.target_id}",
            metadata=metadata,
        )

    def build_integration_record(self, source: RagSource, frontmatter: dict, integration: IntegrationRecord) -> RagDocument:
        view = DocsFrontmatterView(frontmatter)
        source_id = view.document_id or source.path
        integration_id = sha256(f"{source_id}|{integration.target}|{integration.anchor}".encode("utf-8")).hexdigest()
        metadata = {
            "integration_id": integration_id,
            "source_id": source_id,
            "source_type": view.doc_type,
            "target": integration.target,
            "target_type": integration.target_type,
            "direction": integration.direction,
            "interaction": integration.interaction,
            "via": integration.via,
            "purpose": integration.purpose,
            "details": integration.details,
            "domain": view.domain,
            "subdomain": view.subdomain,
            "source_path": source.path,
            "anchor": integration.anchor,
            "artifact_type": "DOCS",
        }
        text = " | ".join(
            part
            for part in [integration.name, integration.target, integration.interaction, integration.via, integration.purpose]
            if part
        )
        return RagDocument(
            layer=RagLayer.DOCS_INTEGRATION_INDEX,
            source=source,
            title=integration.name,
            text=text[:4000] or integration.target,
            metadata=metadata,
        )
