'use client';

import { Canvas } from '@react-three/fiber';
import {
  CameraControls,
  Line,
  Text,
} from '@react-three/drei';
import { Suspense, useEffect, useRef, useState } from 'react';
import Surreal from 'surrealdb';

// Define the shape of nodes and links from DB
interface NodeData {
  id: string;
  title: string;
  coords_3d: [number, number, number];
}

interface LinkData {
  in: string; // from node id
  out: string; // to node id
}

// 1. The 3D Node Component
function Node({ node, onNodeClick }: { node: NodeData; onNodeClick: (node: NodeData) => void }) {
  const [hovered, setHovered] = useState(false);
  const [clicked, setClicked] = useState(false);

  return (
    <mesh
      position={node.coords_3d}
      onClick={(e) => {
        e.stopPropagation();
        onNodeClick(node);
        setClicked(!clicked);
      }}
      onPointerOver={(e) => {
        e.stopPropagation();
        setHovered(true);
      }}
      onPointerOut={() => setHovered(false)}
    >
      <sphereGeometry args={[0.1, 32, 32]} />
      <meshStandardMaterial
        color={hovered ? '#90c0ff' : '#e9ecef'}
        emissive={hovered ? '#90c0ff' : '#e9ecef'}
        emissiveIntensity={hovered ? 0.5 : 0.1}
      />
      {/* Show title on hover or click */}
      {(hovered || clicked) && (
        <Text
          position={[0, 0.2, 0]}
          fontSize={0.1}
          color="white"
          anchorX="center"
          anchorY="middle"
        >
          {node.title}
        </Text>
      )}
    </mesh>
  );
}

// 2. The Main Scene Component
export function ThoughtGalaxy() {
  const [nodes, setNodes] = useState<NodeData[]>([]);
  const [links, setLinks] = useState<LinkData[]>([]);
  const cameraControlsRef = useRef<CameraControls>(null);

  // Fetch data from SurrealDB on mount
  useEffect(() => {
    async function fetchData() {
      // Client-side connection
      const db = new Surreal();
      await db.connect(process.env.NEXT_PUBLIC_SURREALDB_WSS_URL!);

      // Get the token from the cookie
      const tokenCookie = document.cookie
        .split('; ')
        .find((row) => row.startsWith('ponderants-auth='));

      if (!tokenCookie) {
        console.error('[ThoughtGalaxy] No auth token found');
        return;
      }

      const token = tokenCookie.split('=')[1];
      await db.authenticate(token);

      // Fetch nodes that have coordinates
      const nodeResults = await db.query<[NodeData[]]>(
        'SELECT id, title, coords_3d FROM node WHERE coords_3d != NONE'
      );
      setNodes(nodeResults[0] || []);

      // Fetch links
      const linkResults = await db.query<[LinkData[]]>('SELECT in, out FROM links_to');
      setLinks(linkResults[0] || []);

      console.log(`[ThoughtGalaxy] Loaded ${nodeResults[0]?.length || 0} nodes and ${linkResults[0]?.length || 0} links`);
    }
    fetchData();
  }, []);

  // Map links to node positions
  const linkLines = links
    .map((link) => {
      const startNode = nodes.find((n) => n.id === link.in);
      const endNode = nodes.find((n) => n.id === link.out);
      if (startNode && endNode) {
        return {
          start: startNode.coords_3d,
          end: endNode.coords_3d,
        };
      }
      return null;
    })
    .filter(Boolean) as { start: [number, number, number]; end: [number, number, number] }[];

  // Camera animation
  const handleNodeClick = (node: NodeData) => {
    if (cameraControlsRef.current) {
      cameraControlsRef.current.smoothTime = 0.8;
      cameraControlsRef.current.setLookAt(
        node.coords_3d[0] + 1,
        node.coords_3d[1] + 1,
        node.coords_3d[2] + 1,
        node.coords_3d[0],
        node.coords_3d[1],
        node.coords_3d[2],
        true // Enable smooth transition
      );
    }
  };

  return (
    <Canvas camera={{ position: [0, 5, 10], fov: 60 }}>
      <ambientLight intensity={0.5} />
      <pointLight position={[10, 10, 10]} intensity={1} />
      <CameraControls ref={cameraControlsRef} />

      <Suspense fallback={null}>
        <group>
          {/* Render all nodes */}
          {nodes.map((node) => (
            <Node key={node.id} node={node} onNodeClick={handleNodeClick} />
          ))}

          {/* Render all links */}
          {linkLines.map((line, i) => (
            <Line
              key={i}
              points={[line.start, line.end]}
              color="#495057" // gray
              lineWidth={1}
            />
          ))}
        </group>
      </Suspense>
    </Canvas>
  );
}
