"use client";

import { cn } from "@/lib/utils";
import type { ArrayState, PointerState } from "@/lib/visualizations/types";
import { ArrayElement } from "../primitives/array-element";
import { Pointer } from "../primitives/pointer";

interface ArrayViewProps {
  array: ArrayState;
  pointers: PointerState[];
  showIndices?: boolean;
  elementSize?: "sm" | "md" | "lg";
  className?: string;
}

// Must match SIZE_CLASSES in array-element.tsx (Tailwind units × 4)
const ELEMENT_WIDTHS = {
  sm: 40,  // w-10 = 40px
  md: 56,  // w-14 = 56px
  lg: 72,  // w-18 = 72px
} as const;

const ELEMENT_GAPS = {
  sm: 4,
  md: 8,
  lg: 12,
} as const;

export function ArrayView({
  array,
  pointers,
  showIndices = true,
  elementSize = "md",
  className,
}: ArrayViewProps) {
  const elementWidth = ELEMENT_WIDTHS[elementSize];
  const gap = ELEMENT_GAPS[elementSize];

  // Calculate total array width for proper pointer alignment
  const totalWidth = array.elements.length * elementWidth + (array.elements.length - 1) * gap;

  // Check if any pointers are too close together (within 1 index) - hide values to save space
  const hasClosePointers = pointers.length > 1 && pointers.some((p, i) => {
    return pointers.some((other, j) => i !== j && Math.abs(p.index - other.index) <= 1);
  });

  // Group pointers by index to calculate offsets for overlapping pointers at same position
  const pointersByIndex = pointers.reduce((acc, pointer) => {
    const idx = pointer.index;
    if (!acc[idx]) acc[idx] = [];
    acc[idx].push(pointer);
    return acc;
  }, {} as Record<number, PointerState[]>);

  // Calculate horizontal offset for pointers at the same index
  const getPointerOffset = (pointer: PointerState): number => {
    const pointersAtIndex = pointersByIndex[pointer.index] || [];
    if (pointersAtIndex.length <= 1) return 0;

    const pointerIdx = pointersAtIndex.findIndex(p => p.id === pointer.id);
    const totalPointers = pointersAtIndex.length;
    const spacing = 36; // px between overlapping pointers
    return (pointerIdx - (totalPointers - 1) / 2) * spacing;
  };

  return (
    <div className={cn("flex flex-col items-center", className)}>
      {array.label && (
        <span className="mb-2 text-sm font-medium text-[var(--muted-foreground)]">
          {array.label}
        </span>
      )}

      {/* Container that sizes to array width - ensures pointer/array alignment */}
      <div className="relative" style={{ width: totalWidth }}>
        {/* Pointers row */}
        <div className="relative mb-1 h-10">
          {pointers.map((pointer) => (
            <Pointer
              key={pointer.id}
              pointer={pointer}
              elementWidth={elementWidth}
              gap={gap}
              value={array.elements[pointer.index]?.value}
              hideValue={hasClosePointers}
              horizontalOffset={getPointerOffset(pointer)}
            />
          ))}
        </div>

        {/* Array elements */}
        <div
          className="flex"
          style={{ gap: `${gap}px` }}
        >
          {array.elements.map((element) => (
            <ArrayElement
              key={`${array.id}-${element.index}`}
              element={element}
              size={elementSize}
              showIndex={showIndices}
            />
          ))}
        </div>
      </div>
    </div>
  );
}
