import { useCallback, useMemo } from 'react';
import {
  ReactFlow, Background, Controls, MiniMap,
  applyNodeChanges, applyEdgeChanges, type Connection, type NodeChange, type EdgeChange,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { useGraph, type FlowNode } from '../store';
import { BoxNode } from './BoxNode';

export function Canvas() {
  const nodes = useGraph((s) => s.nodes);
  const edges = useGraph((s) => s.edges);
  const setNodes = useGraph((s) => s.setNodes);
  const setEdges = useGraph((s) => s.setEdges);
  const connect = useGraph((s) => s.connect);

  const nodeTypes = useMemo(() => ({ box: BoxNode }), []);

  const onNodesChange = useCallback(
    (changes: NodeChange[]) => setNodes(applyNodeChanges(changes, nodes as any) as unknown as FlowNode[]),
    [nodes, setNodes],
  );
  const onEdgesChange = useCallback(
    (changes: EdgeChange[]) => setEdges(applyEdgeChanges(changes, edges as any) as any),
    [edges, setEdges],
  );
  const onConnect = useCallback(
    (c: Connection) => { if (c.source && c.target) connect(c.source, c.target); },
    [connect],
  );

  return (
    <div className="h-full w-full">
      <ReactFlow
        nodes={nodes as any}
        edges={edges as any}
        nodeTypes={nodeTypes}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        onConnect={onConnect}
        fitView
        proOptions={{ hideAttribution: true }}
      >
        <Background color="#27272a" gap={20} />
        <MiniMap pannable zoomable />
        <Controls />
      </ReactFlow>
    </div>
  );
}
