"""PageRank algorithm over AGE graphs via NetworkX or igraph."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from piggie._integrations.networkx import to_networkx
from piggie.exceptions import AlgorithmError

if TYPE_CHECKING:
    import pandas as pd

    from piggie.driver import PiggieDriver


def _resolve_backend(backend: str) -> str:
    if backend != "auto":
        return backend
    try:
        import igraph  # noqa: F401
        return "igraph"
    except ImportError:
        return "networkx"


def _pagerank_igraph(
    driver: PiggieDriver,
    graph: str,
    *,
    damping: float,
    label: str | None,
    rel_type: str | None,
) -> pd.DataFrame:
    import pandas as pd

    from piggie._integrations.igraph_integration import to_igraph_sql

    G_ig, id_map = to_igraph_sql(driver, graph, directed=True)

    try:
        scores = G_ig.pagerank(directed=True, damping=damping)
    except Exception as exc:
        raise AlgorithmError(f"PageRank computation failed: {exc}") from exc

    rows = []
    for idx, score in enumerate(scores):
        rows.append({
            "node_id": id_map[idx],
            "label": G_ig.vs[idx]["label"],
            "pagerank": score,
        })
    return pd.DataFrame(rows)


def pagerank(
    driver: PiggieDriver,
    graph: str,
    *,
    backend: str = "auto",
    label: str | None = None,
    rel_type: str | None = None,
    damping: float = 0.85,
) -> pd.DataFrame:
    """Compute PageRank for nodes in an AGE graph.

    Args:
        driver: Connected PiggieDriver.
        graph: Graph name.
        backend: Compute backend — "auto" (prefer igraph), "igraph", or
            "networkx".
        label: Filter to a single vertex label (None = all).
        rel_type: Filter to a single edge type (None = all).
        damping: Damping factor (default 0.85).

    Returns:
        DataFrame with columns [node_id, label, pagerank].
    """
    resolved = _resolve_backend(backend)

    if resolved == "igraph":
        return _pagerank_igraph(
            driver, graph, damping=damping, label=label, rel_type=rel_type,
        )

    # NetworkX path
    try:
        import networkx as nx
        import pandas as pd
    except ImportError as exc:
        raise ImportError(
            "networkx and pandas are required. "
            "Install with: pip install piggie[networkx,pandas]"
        ) from exc

    labels = [label] if label else None
    rel_types = [rel_type] if rel_type else None
    G = to_networkx(driver, graph, labels=labels, rel_types=rel_types)

    try:
        scores: dict[Any, float] = nx.pagerank(G, alpha=damping)
    except Exception as exc:
        raise AlgorithmError(f"PageRank computation failed: {exc}") from exc

    rows = []
    for node_id, score in scores.items():
        node_label = G.nodes[node_id].get("label", "")
        rows.append({"node_id": node_id, "label": node_label, "pagerank": score})

    return pd.DataFrame(rows)
