import { useMemo } from "react";
import { useNavigate } from "react-router-dom";
import {
  ReactFlow,
  Background,
  Controls,
  type Node,
  type Edge,
} from "@xyflow/react";
import dagre from "@dagrejs/dagre";
import { useGraph } from "@/hooks/useGraph";
import "@xyflow/react/dist/style.css";

const NODE_WIDTH = 160;
const NODE_HEIGHT = 50;

function layoutGraph(
  nodes: Node[],
  edges: Edge[]
): { nodes: Node[]; edges: Edge[] } {
  const g = new dagre.graphlib.Graph();
  g.setDefaultEdgeLabel(() => ({}));
  g.setGraph({ rankdir: "TB", nodesep: 50, ranksep: 80 });

  nodes.forEach((n) =>
    g.setNode(n.id, { width: NODE_WIDTH, height: NODE_HEIGHT })
  );
  edges.forEach((e) => g.setEdge(e.source, e.target));
  dagre.layout(g);

  const laid = nodes.map((n) => {
    const pos = g.node(n.id);
    return {
      ...n,
      position: { x: pos.x - NODE_WIDTH / 2, y: pos.y - NODE_HEIGHT / 2 },
    };
  });

  return { nodes: laid, edges };
}

export default function GraphView() {
  const { data, loading } = useGraph();
  const navigate = useNavigate();

  const { nodes, edges } = useMemo(() => {
    if (!data) return { nodes: [], edges: [] };

    const rfNodes: Node[] = data.nodes.map((n) => ({
      id: n.id,
      data: { label: n.title ?? n.id },
      position: { x: 0, y: 0 },
      style: {
        background: n.published
          ? "oklch(0.488 0.14 145)"
          : "oklch(0.7 0.15 80)",
        color: "#fff",
        border:
          n.id === "index"
            ? "2px solid oklch(0.6 0.2 250)"
            : "1px solid oklch(1 0 0 / 10%)",
        borderRadius: 8,
        padding: "8px 16px",
        fontSize: 13,
        fontWeight: n.id === "index" ? 700 : 400,
        width: NODE_WIDTH,
      },
    }));

    const rfEdges: Edge[] = data.edges.map((e, i) => ({
      id: `e-${i}`,
      source: e.source,
      target: e.target,
      style: { stroke: "oklch(0.556 0 0)" },
    }));

    return layoutGraph(rfNodes, rfEdges);
  }, [data]);

  if (loading)
    return (
      <div className="flex items-center justify-center h-full text-muted-foreground">
        Loading graph...
      </div>
    );

  return (
    <div className="h-full bg-background">
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodeClick={(_, node) => navigate(`/editor/${node.id}`)}
        fitView
        proOptions={{ hideAttribution: true }}
      >
        <Background color="oklch(0.269 0 0)" gap={20} />
        <Controls />
      </ReactFlow>
    </div>
  );
}
