'use client';

import { useMemo } from 'react';
import { motion } from 'framer-motion';
import { cn } from '@/lib/utils';
import type { HeapState, HeapNodeState } from '@/lib/visualizations/types';
import { HeapNode } from '../primitives/heap-node';

interface HeapViewProps {
  heap: HeapState;
  className?: string;
  showArrayView?: boolean;
}

const NODE_RADIUS = 24;
const LEVEL_HEIGHT = 72;
const MIN_NODE_SPACING = 60;
const SVG_PADDING = 32;
const ARRAY_HEIGHT = 60;

interface NodePosition {
  node: HeapNodeState;
  x: number;
  y: number;
  parentX?: number;
  parentY?: number;
}

function calculateHeapLayout(elements: HeapNodeState[], totalWidth: number): NodePosition[] {
  const positions: NodePosition[] = [];
  if (elements.length === 0) return positions;

  for (let i = 0; i < elements.length; i++) {
    const level = Math.floor(Math.log2(i + 1));
    const posInLevel = i - (Math.pow(2, level) - 1);
    const nodesInLevel = Math.pow(2, level);

    const levelWidth = totalWidth / nodesInLevel;
    const x = levelWidth * (posInLevel + 0.5);
    const y = SVG_PADDING + level * LEVEL_HEIGHT + NODE_RADIUS;

    let parentX: number | undefined;
    let parentY: number | undefined;

    if (i > 0) {
      const parentIndex = Math.floor((i - 1) / 2);
      const parentLevel = Math.floor(Math.log2(parentIndex + 1));
      const parentPosInLevel = parentIndex - (Math.pow(2, parentLevel) - 1);
      const parentNodesInLevel = Math.pow(2, parentLevel);
      const parentLevelWidth = totalWidth / parentNodesInLevel;
      parentX = parentLevelWidth * (parentPosInLevel + 0.5);
      parentY = SVG_PADDING + parentLevel * LEVEL_HEIGHT + NODE_RADIUS;
    }

    positions.push({
      node: elements[i],
      x,
      y,
      parentX,
      parentY,
    });
  }

  return positions;
}

export function HeapView({
  heap,
  className,
  showArrayView = true,
}: HeapViewProps) {
  const { positions, svgWidth, svgHeight, treeHeight } = useMemo(() => {
    if (heap.elements.length === 0) {
      return { positions: [], svgWidth: 200, svgHeight: 100, treeHeight: 50 };
    }

    const depth = Math.floor(Math.log2(heap.elements.length)) + 1;
    const maxNodesAtBottom = Math.pow(2, depth - 1);
    const width = Math.max(
      maxNodesAtBottom * MIN_NODE_SPACING + SVG_PADDING * 2,
      200
    );
    const treeH = depth * LEVEL_HEIGHT + SVG_PADDING;
    const height = treeH + (showArrayView ? ARRAY_HEIGHT : SVG_PADDING);
    const pos = calculateHeapLayout(heap.elements, width);
    return { positions: pos, svgWidth: width, svgHeight: height, treeHeight: treeH };
  }, [heap.elements, showArrayView]);

  const heapTypeLabel = heap.heapType === 'min' ? 'Min-Heap' : 'Max-Heap';
  const sizeLabel = heap.maxSize ? ` (size ≤ ${heap.maxSize})` : '';

  return (
    <div className={cn('flex flex-col items-center', className)}>
      {(heap.label || true) && (
        <span className="mb-2 text-sm font-medium text-[var(--muted-foreground)]">
          {heap.label || heapTypeLabel}{sizeLabel}
        </span>
      )}
      <svg
        width={svgWidth}
        height={svgHeight}
        viewBox={`0 0 ${svgWidth} ${svgHeight}`}
        className="overflow-visible"
      >
        {/* Draw edges first (behind nodes) */}
        {positions.map(({ node, x, y, parentX, parentY }) =>
          parentX !== undefined && parentY !== undefined ? (
            <motion.line
              key={`edge-${node.id}`}
              x1={parentX}
              y1={parentY + NODE_RADIUS}
              x2={x}
              y2={y - NODE_RADIUS}
              className="stroke-[var(--border)]"
              strokeWidth={2}
              initial={false}
              animate={{
                opacity: node.state === 'removing' ? 0.3 : 1,
              }}
              transition={{ duration: 0.2 }}
            />
          ) : null
        )}

        {/* Draw nodes */}
        {positions.map(({ node, x, y }) => (
          <HeapNode
            key={node.id}
            node={node}
            x={x}
            y={y}
            radius={NODE_RADIUS}
          />
        ))}

        {/* Root indicator (kth largest for min-heap top-k) */}
        {positions.length > 0 && positions[0].node.state === 'highlighted' && (
          <g>
            <motion.polygon
              points={`${positions[0].x},${positions[0].y - NODE_RADIUS - 8} ${positions[0].x - 6},${positions[0].y - NODE_RADIUS - 18} ${positions[0].x + 6},${positions[0].y - NODE_RADIUS - 18}`}
              className="fill-[var(--primary)]"
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              transition={{ duration: 0.2 }}
            />
            <motion.text
              x={positions[0].x}
              y={positions[0].y - NODE_RADIUS - 24}
              textAnchor="middle"
              className="fill-[var(--primary)] text-xs font-medium"
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              transition={{ duration: 0.2 }}
            >
              root
            </motion.text>
          </g>
        )}

        {/* Array representation below tree */}
        {showArrayView && heap.elements.length > 0 && (
          <g transform={`translate(0, ${treeHeight})`}>
            <text
              x={SVG_PADDING}
              y={12}
              className="fill-[var(--muted-foreground)] text-xs"
            >
              Array: [{heap.elements.map(e => e.value).join(', ')}]
            </text>
            {/* Index markers */}
            <text
              x={SVG_PADDING}
              y={28}
              className="fill-[var(--muted-foreground)] text-[10px] opacity-70"
            >
              idx:    {heap.elements.map((_, i) => i).join('   ')}
            </text>
          </g>
        )}

        {/* Empty state indicator */}
        {heap.elements.length === 0 && (
          <text
            x={svgWidth / 2}
            y={svgHeight / 2}
            textAnchor="middle"
            className="fill-[var(--muted-foreground)] text-sm italic"
          >
            (empty)
          </text>
        )}
      </svg>
    </div>
  );
}
