"""
Brynq Phase 61: Knowledge Graph Sync
Provides synchronization between decentralized memory nodes and constructs a cohesive knowledge graph.
"""

import json
from typing import Dict, Any, List
from pathlib import Path
from brynq.server import BROKER_DIR, _write_json_sync

GRAPH_DIR = BROKER_DIR / "knowledge_graph"

def _ensure_dir():
    GRAPH_DIR.mkdir(parents=True, exist_ok=True)

def _get_graph_file(namespace: str) -> Path:
    return GRAPH_DIR / f"{namespace}.json"

def add_node(namespace: str, node_id: str, properties: Dict[str, Any]) -> bool:
    """Add a node to the knowledge graph."""
    _ensure_dir()
    path = _get_graph_file(namespace)
    
    try:
        graph = json.loads(path.read_text("utf-8")) if path.exists() else {"nodes": {}, "edges": []}
        graph["nodes"][node_id] = properties
        _write_json_sync(path, graph)
        return True
    except Exception:
        return False

def add_edge(namespace: str, source_id: str, target_id: str, relationship: str) -> bool:
    """Add an edge (relationship) between two nodes."""
    _ensure_dir()
    path = _get_graph_file(namespace)
    
    try:
        graph = json.loads(path.read_text("utf-8")) if path.exists() else {"nodes": {}, "edges": []}
        edge = {"source": source_id, "target": target_id, "relationship": relationship}
        if edge not in graph["edges"]:
            graph["edges"].append(edge)
            _write_json_sync(path, graph)
        return True
    except Exception:
        return False

def get_graph(namespace: str) -> Dict[str, Any]:
    """Retrieve the entire knowledge graph for a given namespace."""
    path = _get_graph_file(namespace)
    if not path.exists():
        return {"nodes": {}, "edges": []}
    try:
        return json.loads(path.read_text("utf-8"))
    except Exception:
        return {"nodes": {}, "edges": []}

def get_node_edges(namespace: str, node_id: str) -> List[Dict[str, str]]:
    """Get all edges connected to a specific node."""
    graph = get_graph(namespace)
    return [e for e in graph.get("edges", []) if e["source"] == node_id or e["target"] == node_id]
