"""Canonical knowledge routing for SDK graph/vector integrations.

Prefers IKE for durable knowledge writes and can optionally mirror into
legacy GraphRAG vector storage for compatibility during migration.
"""

from __future__ import annotations

import logging
from typing import Any, Dict, List, Optional

logger = logging.getLogger(__name__)


class KnowledgeRouter:
    """Route durable knowledge writes to IKE and optional legacy mirrors."""

    def __init__(
        self,
        config: Any = None,
        ike_bridge: Any = None,
        vector_store: Any = None,
        embedder: Any = None,
    ) -> None:
        self._config = config
        self._ike = ike_bridge
        self._vector_store = vector_store
        self._embedder = embedder
        self._mode = getattr(config, "knowledge_backend", "legacy") if config else "legacy"
        self._legacy_enabled = (
            getattr(config, "legacy_graph_vector_enabled", True) if config else True
        )

    @property
    def mode(self) -> str:
        return self._mode

    @property
    def prefers_ike(self) -> bool:
        return self._mode in {"ike", "hybrid"}

    @property
    def allows_legacy(self) -> bool:
        return self._legacy_enabled and self._mode in {"legacy", "hybrid"}

    @property
    def available(self) -> bool:
        return self.ike_available or self.legacy_available

    @property
    def ike_available(self) -> bool:
        return self.prefers_ike and self._ike is not None and getattr(self._ike, "available", False)

    @property
    def legacy_available(self) -> bool:
        return self.allows_legacy and self._vector_store is not None and self._embedder is not None

    def ingest_entry(
        self,
        doc_id: str,
        content: str,
        source_type: str,
        metadata: Optional[Dict[str, Any]] = None,
        tags: Optional[List[str]] = None,
        trace_id: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Ingest content into the canonical knowledge plane and optional legacy mirror."""
        meta: Dict[str, Any] = dict(metadata or {})
        meta.setdefault("source_type", source_type)
        if trace_id:
            meta["trace_id"] = trace_id
        normalized_tags = list(tags or [source_type])
        result: Dict[str, Any] = {
            "ok": False,
            "mode": self._mode,
            "ike_entry_id": None,
            "legacy_indexed": False,
            "errors": [],
        }

        if self.ike_available:
            try:
                entry_id = self._ike.ingest_knowledge(
                    content=content,
                    source_type=source_type,
                    tags=normalized_tags,
                    source_id=doc_id,
                    metadata=meta,
                )
                if entry_id:
                    result["ike_entry_id"] = entry_id
                    result["ok"] = True
                else:
                    result["errors"].append("ike_ingest_failed")
            except Exception as exc:
                logger.warning("KnowledgeRouter IKE ingest failed for %s: %s", doc_id, exc)
                result["errors"].append("ike_ingest_failed")
        elif self.prefers_ike:
            result["errors"].append("ike_unavailable")

        if self.legacy_available:
            try:
                embedding = self._embedder.embed(content)
                legacy_ok = bool(
                    self._vector_store.upsert(
                        id=doc_id,
                        embedding=embedding,
                        content=content,
                        metadata=meta,
                    )
                )
                result["legacy_indexed"] = legacy_ok
                result["ok"] = result["ok"] or legacy_ok
                if not legacy_ok:
                    result["errors"].append("legacy_upsert_failed")
            except Exception as exc:
                logger.warning("KnowledgeRouter legacy ingest failed for %s: %s", doc_id, exc)
                result["errors"].append("legacy_upsert_failed")
        elif self.allows_legacy and self._mode == "legacy":
            result["errors"].append("legacy_unavailable")

        return result

    def query_knowledge(
        self,
        query: str,
        top_k: int = 10,
        **kwargs: Any,
    ) -> Optional[Dict[str, Any]]:
        """Query IKE's knowledge plane when available."""
        if not self.ike_available:
            return None
        try:
            return self._ike.query_knowledge(query=query, top_k=top_k, **kwargs)
        except Exception as exc:
            logger.warning("KnowledgeRouter query failed: %s", exc)
            return None
