import { Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
import type { Lap } from "../../types/api";

function paceSecPerKm(mps: number | null): number | null {
  if (mps == null || mps <= 0) return null;
  return 1000 / mps;
}

function formatPaceShort(secPerKm: number): string {
  const m = Math.floor(secPerKm / 60);
  const s = Math.round(secPerKm % 60);
  return `${m}:${s.toString().padStart(2, "0")}`;
}

function formatPace(secPerKm: number): string {
  return `${formatPaceShort(secPerKm)}/km`;
}

// Recharts' "dataMin - N" domain expressions don't combine reliably with
// reversed axes, so the padded numeric domain is computed directly instead.
function paddedDomain(values: Array<number | null | undefined>, pad: number): [number, number] {
  const nums = values.filter((v): v is number => v != null);
  if (nums.length === 0) return [0, 1];
  return [Math.min(...nums) - pad, Math.max(...nums) + pad];
}

// Shows each lap's actual pace/HR against the expected band from the
// activity's structured Garmin workout (see backend's alignWorkoutTargets).
// Renders nothing if no lap has a resolved target -- most activities aren't
// from a structured workout, and an empty chart isn't useful.
export function ExpectedVsActualChart({ laps }: { laps: Lap[] }) {
  const hasPaceTarget = laps.some((l) => l.TargetPaceLowMps != null && l.TargetPaceHighMps != null);
  const hasHRTarget = laps.some((l) => l.TargetHRLowBpm != null && l.TargetHRHighBpm != null);
  if (!hasPaceTarget && !hasHRTarget) return null;

  const data = laps.map((l, i) => ({
    lap: i + 1,
    actualPace: paceSecPerKm(l.AvgSpeedMps),
    // Pace (sec/km) is inverted vs speed (m/s): the *faster* (higher) speed
    // bound is the *lower* (faster) pace bound.
    targetPaceLow: l.TargetPaceHighMps != null ? paceSecPerKm(l.TargetPaceHighMps) : null,
    targetPaceHigh: l.TargetPaceLowMps != null ? paceSecPerKm(l.TargetPaceLowMps) : null,
    actualHR: l.AvgHR,
    targetHRLow: l.TargetHRLowBpm,
    targetHRHigh: l.TargetHRHighBpm,
  }));

  const paceDomain = paddedDomain(data.flatMap((d) => [d.actualPace, d.targetPaceLow, d.targetPaceHigh]), 10);
  const hrDomain = paddedDomain(data.flatMap((d) => [d.actualHR, d.targetHRLow, d.targetHRHigh]), 5);

  return (
    <div className="expected-actual-charts">
      {hasPaceTarget && (
        <div className="mini-chart">
          <span className="mini-chart-label">Pace vs target</span>
          <ResponsiveContainer width="100%" height={90}>
            <LineChart data={data} margin={{ top: 4, right: 4, bottom: 0, left: 4 }}>
              <XAxis dataKey="lap" tick={{ fontSize: 10 }} />
              <YAxis
                reversed
                domain={paceDomain}
                tick={{ fontSize: 10 }}
                width={34}
                tickFormatter={(v) => formatPaceShort(Number(v))}
              />
              <Tooltip
                formatter={(v) => formatPace(Number(v))}
                labelFormatter={(l) => `Lap ${l}`}
                contentStyle={{ fontSize: 12 }}
              />
              <Line type="stepAfter" dataKey="targetPaceLow" stroke="#9aa0ab" strokeDasharray="3 3" dot={false} isAnimationActive={false} name="Target low" />
              <Line type="stepAfter" dataKey="targetPaceHigh" stroke="#9aa0ab" strokeDasharray="3 3" dot={false} isAnimationActive={false} name="Target high" />
              <Line type="monotone" dataKey="actualPace" stroke="#3b82f6" strokeWidth={2} dot={{ r: 2 }} isAnimationActive={false} name="Actual" />
            </LineChart>
          </ResponsiveContainer>
        </div>
      )}
      {hasHRTarget && (
        <div className="mini-chart">
          <span className="mini-chart-label">HR vs target</span>
          <ResponsiveContainer width="100%" height={90}>
            <LineChart data={data} margin={{ top: 4, right: 4, bottom: 0, left: 4 }}>
              <XAxis dataKey="lap" tick={{ fontSize: 10 }} />
              <YAxis domain={hrDomain} tick={{ fontSize: 10 }} width={30} tickFormatter={(v) => String(Math.round(Number(v)))} />
              <Tooltip formatter={(v) => `${Math.round(Number(v))} bpm`} labelFormatter={(l) => `Lap ${l}`} contentStyle={{ fontSize: 12 }} />
              <Line type="stepAfter" dataKey="targetHRLow" stroke="#9aa0ab" strokeDasharray="3 3" dot={false} isAnimationActive={false} name="Target low" />
              <Line type="stepAfter" dataKey="targetHRHigh" stroke="#9aa0ab" strokeDasharray="3 3" dot={false} isAnimationActive={false} name="Target high" />
              <Line type="monotone" dataKey="actualHR" stroke="#ef4444" strokeWidth={2} dot={{ r: 2 }} isAnimationActive={false} name="Actual" />
            </LineChart>
          </ResponsiveContainer>
        </div>
      )}
    </div>
  );
}
