"use client";

import { useMemo } from "react";
import type { ArrayState, ElementState } from "@/types/visualization";

interface ArrayVisualizerProps {
  data: ArrayState;
  name?: string;
}

const CELL_WIDTH = 56;
const CELL_HEIGHT = 56;
const CELL_GAP = 4;
const INDEX_AREA_HEIGHT = 20;
const POINTER_HEIGHT = 24;
const ANNOTATION_HEIGHT = 20;
const SVG_PADDING = 16;

function getStateColor(state: ElementState): string {
  switch (state) {
    case "active":
      return "var(--viz-active)";
    case "comparing":
      return "var(--viz-comparing)";
    case "found":
      return "var(--viz-found)";
    case "visited":
      return "var(--viz-visited)";
    case "swapping":
      return "var(--viz-swapping)";
    default:
      return "var(--viz-default)";
  }
}

function getTextColor(state: ElementState): string {
  switch (state) {
    case "active":
    case "found":
    case "swapping":
      return "white";
    case "comparing":
      return "var(--foreground)";
    case "visited":
      return "var(--muted-foreground)";
    default:
      return "var(--foreground)";
  }
}

export function ArrayVisualizer({ data, name }: ArrayVisualizerProps) {
  const { values, pointers = {} } = data;

  const dimensions = useMemo(() => {
    const hasPointers = Object.keys(pointers).length > 0;
    const hasAnnotations = values.some(
      (v) => v.annotations && v.annotations.length > 0
    );

    const contentWidth =
      values.length * CELL_WIDTH + (values.length - 1) * CELL_GAP;
    const width = contentWidth + SVG_PADDING * 2;

    let height = CELL_HEIGHT + INDEX_AREA_HEIGHT + SVG_PADDING * 2;
    if (hasPointers) height += POINTER_HEIGHT + 16;
    if (hasAnnotations) height += ANNOTATION_HEIGHT;

    return {
      width,
      height,
      contentWidth,
      hasPointers,
      hasAnnotations,
      startX: SVG_PADDING,
      startY: hasAnnotations
        ? SVG_PADDING + ANNOTATION_HEIGHT
        : SVG_PADDING + 8,
    };
  }, [values, pointers]);

  // Group pointers by position for stacking
  const pointersByPosition = useMemo(() => {
    const grouped: Record<number, string[]> = {};
    for (const [label, index] of Object.entries(pointers)) {
      if (!grouped[index]) {
        grouped[index] = [];
      }
      grouped[index].push(label);
    }
    return grouped;
  }, [pointers]);

  return (
    <div className="flex flex-col gap-2">
      {name && (
        <span className="text-sm font-medium text-muted-foreground">
          {name}
        </span>
      )}
      <div className="overflow-x-auto">
        <svg
          width={dimensions.width}
          height={dimensions.height}
          viewBox={`0 0 ${dimensions.width} ${dimensions.height}`}
          className="viz-array"
          role="img"
          aria-label={`Array visualization with ${values.length} elements`}
        >
          {/* Array cells */}
          <g>
            {values.map((element, index) => {
              const x = dimensions.startX + index * (CELL_WIDTH + CELL_GAP);
              const y = dimensions.startY;

              return (
                <g
                  key={index}
                  className="viz-element"
                  data-state={element.state}
                >
                  {/* Cell background */}
                  <rect
                    x={x}
                    y={y}
                    width={CELL_WIDTH}
                    height={CELL_HEIGHT}
                    rx={6}
                    fill={getStateColor(element.state)}
                    className="viz-cell-bg"
                  />

                  {/* Cell border */}
                  <rect
                    x={x}
                    y={y}
                    width={CELL_WIDTH}
                    height={CELL_HEIGHT}
                    rx={6}
                    fill="none"
                    stroke="var(--border)"
                    strokeWidth={1}
                  />

                  {/* Value */}
                  <text
                    x={x + CELL_WIDTH / 2}
                    y={y + CELL_HEIGHT / 2}
                    textAnchor="middle"
                    dominantBaseline="middle"
                    className="viz-value"
                    fill={getTextColor(element.state)}
                    fontSize={18}
                    fontWeight={500}
                    fontFamily="var(--font-mono, monospace)"
                  >
                    {String(element.value)}
                  </text>

                  {/* Annotations (above cell) */}
                  {element.annotations && element.annotations.length > 0 && (
                    <text
                      x={x + CELL_WIDTH / 2}
                      y={y - 6}
                      textAnchor="middle"
                      className="viz-annotation"
                      fill="var(--primary)"
                      fontSize={12}
                      fontWeight={600}
                    >
                      {element.annotations.join(", ")}
                    </text>
                  )}
                </g>
              );
            })}
          </g>

          {/* Pointers (below cells, before indices) */}
          {dimensions.hasPointers && (
            <g className="viz-pointers">
              {Object.entries(pointersByPosition).map(([posStr, labels]) => {
                const position = parseInt(posStr, 10);
                if (position < 0 || position >= values.length) return null;

                const x =
                  dimensions.startX +
                  position * (CELL_WIDTH + CELL_GAP) +
                  CELL_WIDTH / 2;
                const y =
                  dimensions.startY + CELL_HEIGHT + INDEX_AREA_HEIGHT + POINTER_HEIGHT;

                return (
                  <g key={posStr} className="viz-pointer">
                    {/* Arrow */}
                    <line
                      x1={x}
                      y1={y}
                      x2={x}
                      y2={y - 10}
                      stroke="var(--primary)"
                      strokeWidth={2}
                      markerEnd="url(#arrowhead)"
                    />

                    {/* Label(s) */}
                    <text
                      x={x}
                      y={y + 12}
                      textAnchor="middle"
                      fill="var(--primary)"
                      fontSize={12}
                      fontWeight={600}
                      fontFamily="var(--font-mono, monospace)"
                    >
                      {labels.join(", ")}
                    </text>
                  </g>
                );
              })}
            </g>
          )}

          {/* Index labels (rendered last to appear on top) */}
          <g className="viz-indices">
            {values.map((_, index) => {
              const x = dimensions.startX + index * (CELL_WIDTH + CELL_GAP);
              const y = dimensions.startY;

              return (
                <text
                  key={index}
                  x={x + CELL_WIDTH / 2}
                  y={y + CELL_HEIGHT + INDEX_AREA_HEIGHT / 2 + 4}
                  textAnchor="middle"
                  dominantBaseline="middle"
                  className="viz-index"
                  fill="var(--muted-foreground)"
                  fontSize={11}
                >
                  {index}
                </text>
              );
            })}
          </g>

          {/* Arrow marker definition */}
          <defs>
            <marker
              id="arrowhead"
              markerWidth="8"
              markerHeight="6"
              refX="0"
              refY="3"
              orient="auto"
            >
              <polygon points="0 0, 8 3, 0 6" fill="var(--primary)" />
            </marker>
          </defs>
        </svg>
      </div>
    </div>
  );
}
