import { useMemo } from 'react';
import {
  ScatterChart, Scatter, XAxis, YAxis, Tooltip,
  ResponsiveContainer, Rectangle,
} from 'recharts';
import { rechartsTheme } from '@cameleer/design-system';

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

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

const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

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

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

interface HeatmapPoint {
  weekday: number;
  hour: number;
  value: number;
  fill: string;
}

function HeatmapCell(props: Record<string, unknown>) {
  const { cx, cy, payload } = props as {
    cx: number; cy: number; payload: HeatmapPoint;
  };
  if (!payload) return null;
  // Cell size: chart area / grid divisions. Approximate from scatter positioning.
  const cellW = 32;
  const cellH = 10;
  return (
    <Rectangle
      x={cx - cellW / 2}
      y={cy - cellH / 2}
      width={cellW}
      height={cellH}
      fill={payload.fill}
      radius={2}
    />
  );
}

function formatDay(value: number): string {
  return DAYS[value] ?? '';
}

function formatHour(value: number): string {
  return String(value).padStart(2, '0');
}

export function PunchcardHeatmap({ cells, mode }: PunchcardHeatmapProps) {
  const data: HeatmapPoint[] = useMemo(() => {
    const values = cells.map(c => mode === 'errors' ? c.failedCount : c.totalCount);
    const maxVal = Math.max(...values, 1);

    // Build full 7x24 grid
    const points: HeatmapPoint[] = [];
    const cellMap = new Map<string, PunchcardCell>();
    for (const c of cells) cellMap.set(`${c.weekday}-${c.hour}`, c);

    for (let d = 0; d < 7; d++) {
      for (let h = 0; h < 24; h++) {
        const cell = cellMap.get(`${d}-${h}`);
        const val = cell ? (mode === 'errors' ? cell.failedCount : cell.totalCount) : 0;
        const ratio = maxVal > 0 ? val / maxVal : 0;
        points.push({
          weekday: d,
          hour: h,
          value: val,
          fill: mode === 'errors' ? errorColor(ratio) : transactionColor(ratio),
        });
      }
    }
    return points;
  }, [cells, mode]);

  return (
    <ResponsiveContainer width="100%" height={300}>
      <ScatterChart margin={{ top: 10, right: 10, bottom: 10, left: 10 }}>
        <XAxis
          type="number"
          dataKey="weekday"
          domain={[0, 6]}
          ticks={[0, 1, 2, 3, 4, 5, 6]}
          tickFormatter={formatDay}
          {...rechartsTheme.xAxis}
        />
        <YAxis
          type="number"
          dataKey="hour"
          domain={[0, 23]}
          ticks={[0, 4, 8, 12, 16, 20]}
          tickFormatter={formatHour}
          reversed
          {...rechartsTheme.yAxis}
        />
        <Tooltip
          contentStyle={rechartsTheme.tooltip.contentStyle}
          labelStyle={rechartsTheme.tooltip.labelStyle}
          itemStyle={rechartsTheme.tooltip.itemStyle}
          cursor={false}
          formatter={(_val: unknown, _name: string, entry: { payload?: HeatmapPoint }) => {
            const p = entry.payload;
            if (!p) return '';
            return [`${p.value.toLocaleString()} ${mode}`, `${DAYS[p.weekday]} ${formatHour(p.hour)}:00`];
          }}
          labelFormatter={() => ''}
        />
        <Scatter
          data={data}
          shape={(props: unknown) => <HeatmapCell {...(props as Record<string, unknown>)} />}
          isAnimationActive={false}
        />
      </ScatterChart>
    </ResponsiveContainer>
  );
}
