"""Graph helper utilities."""

from __future__ import annotations

from typing import Dict, Iterable, List, Set, Tuple

from ..adt_types import ResourceNode, ResourceRelationship


def ensure_unique_nodes(nodes: Iterable[ResourceNode]) -> List[ResourceNode]:
    """Remove duplicate nodes preserving last occurrence."""

    seen: Dict[str, ResourceNode] = {}
    for node in nodes:
        if node.id in seen:
            del seen[node.id]
        seen[node.id] = node
    return list(seen.values())


def filter_relationships_to_known_nodes(
    nodes: Iterable[ResourceNode],
    relationships: Iterable[ResourceRelationship],
) -> List[ResourceRelationship]:
    """Drop edges whose endpoints do not exist in the node set."""

    node_ids: Set[str] = {n.id for n in nodes}
    return [
        r
        for r in relationships
        if r.source_id in node_ids and r.target_id in node_ids
    ]


def ensure_unique_relationships(
    relationships: Iterable[ResourceRelationship],
) -> List[ResourceRelationship]:
    """Remove duplicate relationships deterministically.

    De-duplicates by (source_id, target_id, relation_type). For duplicates, the
    relationship with the highest weight wins.
    """

    items = sorted(
        relationships,
        key=lambda r: (r.source_id, r.target_id, r.relation_type, -float(r.weight)),
    )

    seen: Set[Tuple[str, str, str]] = set()
    out: List[ResourceRelationship] = []
    for r in items:
        key = (r.source_id, r.target_id, r.relation_type)
        if key in seen:
            continue
        seen.add(key)
        out.append(r)
    return out


def build_graph_edges(
    nodes: Iterable[ResourceNode],
    include_relationships: bool,
) -> List[ResourceRelationship]:
    """Create inferred relationships if required."""

    if not include_relationships:
        return []

    node_map = {node.id: node for node in nodes}
    edges: List[ResourceRelationship] = []
    for node in node_map.values():
        for dependency_id in node.dependencies:
            if dependency_id in node_map:
                edges.append(
                    ResourceRelationship(
                        source_id=node.id,
                        target_id=dependency_id,
                        relation_type="depends_on",
                    )
                )
    return edges
