/* QueueHeatmap — open tickets by queue × priority.
 *
 * Geometric grid; each cell is a square tinted with the brand blue.
 * Intensity scales linearly to the most-loaded cell (so the heaviest
 * cell renders at full saturation).  Per-row totals on the right; the
 * column headers carry priority labels.
 *
 * Empty cells render as a thin dashed outline rather than nothing —
 * preserves the grid alignment and makes the absence visible. */

'use client';

import { priorityBadge } from '@/lib/status-registry';
import { cn } from '@/lib/utils';

interface HeatmapRow {
  queueId: number;
  queueLabel: string;
  total: number;
  byPriority: Record<number, number>;
}

interface QueueHeatmapProps {
  data: HeatmapRow[];
  /** Priority IDs in column order. Defaults to Critical→Very Low. */
  priorities?: number[];
}

const DEFAULT_PRIORITIES = [2, 3, 4, 6, 7];

export function QueueHeatmap({ data, priorities = DEFAULT_PRIORITIES }: QueueHeatmapProps) {
  const max = data.reduce(
    (m, row) => Math.max(m, ...priorities.map((p) => row.byPriority[p] ?? 0)),
    1,
  );

  if (data.length === 0) {
    return (
      <p className="text-sm text-muted-foreground py-4">
        No open tickets.
      </p>
    );
  }

  return (
    <div className="overflow-x-auto">
      <table className="w-full text-sm border-separate border-spacing-x-1 border-spacing-y-0">
        <thead>
          <tr>
            <th className="text-left metric-label py-1 pr-3">Queue</th>
            {priorities.map((p) => {
              const badge = priorityBadge(p);
              return (
                <th key={p} className="metric-label py-1 px-1 text-center w-12">
                  {badge.label.slice(0, 3)}
                </th>
              );
            })}
            <th className="metric-label py-1 pl-3 text-right">Total</th>
          </tr>
        </thead>
        <tbody>
          {data.map((row) => (
            <tr key={row.queueId} className="hover:bg-muted/30">
              <td
                className="py-1 pr-3 truncate max-w-[260px]"
                title={row.queueLabel}
              >
                {row.queueLabel}
              </td>
              {priorities.map((p) => (
                <Cell
                  key={p}
                  value={row.byPriority[p] ?? 0}
                  max={max}
                  priorityLabel={priorityBadge(p).label}
                  queueLabel={row.queueLabel}
                />
              ))}
              <td className="py-1 pl-3 num text-right text-muted-foreground">
                {row.total}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function Cell({
  value,
  max,
  priorityLabel,
  queueLabel,
}: {
  value: number;
  max: number;
  priorityLabel: string;
  queueLabel: string;
}) {
  if (value === 0) {
    return (
      <td className="py-1 px-1">
        <div
          className="h-7 w-full rounded-sm border border-dashed border-border/50"
          aria-label="0"
        />
      </td>
    );
  }
  // Normalize 0..1 then floor into one of 6 opacity steps; smallest cell still
  // reads, largest is at 0.85.
  const ratio = Math.min(value / max, 1);
  const opacity = Math.max(0.18, ratio * 0.85);
  return (
    <td className="py-1 px-1">
      <div
        className={cn(
          'h-7 w-full rounded-sm flex items-center justify-center num text-xs',
          'transition-opacity hover:opacity-100',
        )}
        style={{
          backgroundColor: `color-mix(in oklch, var(--primary) ${Math.round(opacity * 100)}%, transparent)`,
          color: ratio > 0.55 ? 'var(--primary-foreground)' : 'var(--foreground)',
        }}
        title={`${queueLabel} · ${priorityLabel}: ${value}`}
        aria-label={`${queueLabel}, ${priorityLabel}: ${value}`}
      >
        {value}
      </div>
    </td>
  );
}
