import { useMemo } from 'react';

export interface PunchcardCell {
  weekday: number;
  hour: number;
  totalCount: number;
  failedCount: number;
}

interface PunchcardHeatmapProps {
  cells: PunchcardCell[];
  mode: 'transactions' | 'errors';
  width: number;
  height: number;
}

const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
const LEFT_MARGIN = 28;
const TOP_MARGIN = 18;
const BOTTOM_MARGIN = 4;
const RIGHT_MARGIN = 4;

function transactionColor(ratio: number): string {
  if (ratio === 0) return 'hsl(220, 15%, 95%)';
  const lightness = 90 - ratio * 55;
  return `hsl(220, 60%, ${Math.round(lightness)}%)`;
}

function errorColor(ratio: number): string {
  if (ratio === 0) return 'hsl(0, 10%, 95%)';
  const lightness = 90 - ratio * 55;
  return `hsl(0, 65%, ${Math.round(lightness)}%)`;
}

export function PunchcardHeatmap({ cells, mode, width, height }: PunchcardHeatmapProps) {
  const grid = useMemo(() => {
    const map = new Map<string, PunchcardCell>();
    for (const c of cells) {
      map.set(`${c.weekday}-${c.hour}`, c);
    }

    const values: number[] = [];
    for (const c of cells) {
      values.push(mode === 'errors' ? c.failedCount : c.totalCount);
    }
    const maxVal = Math.max(...values, 1);

    const gridWidth = width - LEFT_MARGIN - RIGHT_MARGIN;
    const gridHeight = height - TOP_MARGIN - BOTTOM_MARGIN;
    const cellW = gridWidth / 7;
    const cellH = gridHeight / 24;

    const rects: { x: number; y: number; w: number; h: number; fill: string; value: number; day: string; hour: number }[] = [];

    for (let d = 0; d < 7; d++) {
      for (let h = 0; h < 24; h++) {
        const cell = map.get(`${d}-${h}`);
        const val = cell ? (mode === 'errors' ? cell.failedCount : cell.totalCount) : 0;
        const ratio = maxVal > 0 ? val / maxVal : 0;
        const fill = mode === 'errors' ? errorColor(ratio) : transactionColor(ratio);

        rects.push({
          x: LEFT_MARGIN + d * cellW,
          y: TOP_MARGIN + h * cellH,
          w: cellW,
          h: cellH,
          fill,
          value: val,
          day: DAYS[d],
          hour: h,
        });
      }
    }
    return { rects, cellW, cellH };
  }, [cells, mode, width, height]);

  return (
    <svg viewBox={`0 0 ${width} ${height}`} style={{ width: '100%', height: 'auto', display: 'block' }}>
      {/* Day labels (top) */}
      {DAYS.map((day, i) => (
        <text
          key={day}
          x={LEFT_MARGIN + i * grid.cellW + grid.cellW / 2}
          y={12}
          textAnchor="middle"
          fill="var(--text-muted)"
          fontSize={9}
          fontFamily="var(--font-mono)"
        >
          {day}
        </text>
      ))}

      {/* Hour labels (left, every 4 hours) */}
      {[0, 4, 8, 12, 16, 20].map((h) => (
        <text
          key={h}
          x={LEFT_MARGIN - 4}
          y={TOP_MARGIN + h * grid.cellH + grid.cellH / 2 + 3}
          textAnchor="end"
          fill="var(--text-muted)"
          fontSize={8}
          fontFamily="var(--font-mono)"
        >
          {String(h).padStart(2, '0')}
        </text>
      ))}

      {/* Cells */}
      {grid.rects.map((r) => (
        <rect
          key={`${r.day}-${r.hour}`}
          x={r.x + 0.5}
          y={r.y + 0.5}
          width={Math.max(r.w - 1, 0)}
          height={Math.max(r.h - 1, 0)}
          rx={1.5}
          fill={r.fill}
        >
          <title>{`${r.day} ${String(r.hour).padStart(2, '0')}:00 — ${r.value.toLocaleString()} ${mode}`}</title>
        </rect>
      ))}
    </svg>
  );
}
