import { notFound } from "next/navigation";
import { AiAnalysisCard } from "@/components/ai-analysis-card";
import { ElevationChart } from "@/components/elevation-chart";
import { NotesEditor } from "@/components/notes-editor";
import { RouteMapSection } from "@/components/route-map-section";
import { GcbChart } from "@/components/gcb-chart";
import { RunMetricChart } from "@/components/run-metric-chart";
import { StatCard } from "@/components/stat-card";
import { formatDate, formatDistance, formatDuration, formatPace } from "@/lib/format";
import { getLatestAnalysisForTarget, serializeAnalysis } from "@/lib/models/analysis";
import {
  getRunningActivity,
  type RunningActivity,
} from "@/lib/models/running";
import { getCurrentUserId } from "@/lib/session";
import { saveRunningNotes } from "@/app/running/actions";

export const dynamic = "force-dynamic";

const CHART_SAMPLES = 200;

function interpolate(sorted: { dist: number; value: number }[], target: number): number | null {
  if (sorted.length === 0) return null;
  if (target <= sorted[0].dist) return sorted[0].value;
  if (target >= sorted[sorted.length - 1].dist) return sorted[sorted.length - 1].value;
  let lo = 0;
  let hi = sorted.length - 1;
  while (lo + 1 < hi) {
    const mid = (lo + hi) >> 1;
    if (sorted[mid].dist <= target) lo = mid; else hi = mid;
  }
  const t = (target - sorted[lo].dist) / (sorted[hi].dist - sorted[lo].dist);
  return sorted[lo].value + t * (sorted[hi].value - sorted[lo].value);
}

function buildGrid(maxDistKm: number): number[] {
  return Array.from({ length: CHART_SAMPLES }, (_, i) =>
    Math.round((i / (CHART_SAMPLES - 1)) * maxDistKm * 100) / 100
  );
}

function RouteMap({ activity }: { activity: RunningActivity }) {
  const routePoints = activity.routePoints;
  return (
    <div className="col-span-2 row-span-3 min-h-[240px] overflow-hidden rounded-2xl border border-white/10">
      {routePoints && routePoints.length > 0 ? (
        <RouteMapSection points={routePoints} />
      ) : (
        <div className="flex h-full min-h-[240px] items-center justify-center bg-surface">
          <span className="text-sm text-fg/30">Brak danych GPS — zsynchronizuj ponownie</span>
        </div>
      )}
    </div>
  );
}

function buildChartData(activity: RunningActivity) {
  const maxDistKm = Math.round(activity.distanceM / 10) / 100;
  const grid = buildGrid(maxDistKm);

  const elevProfile = activity.elevationProfile;
  const metrics = activity.runMetrics;

  const elevSorted = elevProfile
    ? elevProfile
        .map((altM, i) => ({ dist: (i / elevProfile.length) * maxDistKm, value: altM }))
        .filter((p) => p.value > 0)
    : [];

  const metricsDistKm = metrics
    ? (() => {
        const raw = metrics.distanceKm;
        const max = Math.max(...raw);
        return max > 0
          ? raw
          : raw.map((_, i) => Math.round(((i / (raw.length - 1)) * maxDistKm) * 100) / 100);
      })()
    : [];

  const hrSorted = metrics?.hrBpm
    ? metricsDistKm
        .map((d, i) => ({ dist: d, value: metrics.hrBpm![i] ?? 0 }))
        .filter((p) => p.value > 0)
    : [];

  const paceSorted = metrics?.paceSec
    ? metricsDistKm
        .map((d, i) => ({ dist: d, value: metrics.paceSec![i] ?? 0 }))
        .filter((p) => p.value > 0 && p.value < 1800)
    : [];

  const gcbSorted = metrics?.gcbLeftPct
    ? metricsDistKm
        .map((d, i) => ({ dist: d, value: metrics.gcbLeftPct![i] ?? 0 }))
        .filter((p) => p.value > 0)
    : [];

  const hasElev = elevSorted.length >= 2;
  const hasHr = hrSorted.length >= 2;
  const hasGcb = gcbSorted.length >= 2;

  const elevData = hasElev
    ? grid.map((distanceKm) => {
        const altM = interpolate(elevSorted, distanceKm) ?? 0;
        const paceSec = paceSorted.length >= 2 ? interpolate(paceSorted, distanceKm) ?? undefined : undefined;
        return { distanceKm, altM, paceSec };
      })
    : null;

  const hrData = hasHr
    ? grid.map((distanceKm) => ({ distanceKm, value: interpolate(hrSorted, distanceKm) ?? 0 }))
    : null;

  const gcbData = hasGcb
    ? grid.map((distanceKm) => {
        const left = Math.round((interpolate(gcbSorted, distanceKm) ?? 50) * 10) / 10;
        return { distanceKm, left, right: Math.round((100 - left) * 10) / 10 };
      })
    : null;

  return { elevData, hrData, gcbData };
}


export default async function RunningActivityPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const userId = await getCurrentUserId();
  const activity = await getRunningActivity(userId, id);

  if (!activity) {
    notFound();
  }

  const analysis = await getLatestAnalysisForTarget(userId, "running", activity._id);
  const { elevData, hrData, gcbData } = buildChartData(activity);

  return (
    <div className="flex flex-col gap-6">
      <div>
        <h1 className="text-2xl font-bold text-fg">{activity.name}</h1>
        <p className="mt-1 text-sm text-fg/60">{formatDate(activity.startTime)}</p>
      </div>

      <section className="grid grid-cols-3 gap-4">
        <RouteMap activity={activity} />

        <StatCard highlight label="Dystans" value={formatDistance(activity.distanceM)} />
        <StatCard highlight label="Czas" value={formatDuration(activity.durationSec)} />
        <StatCard highlight label="Tempo" value={formatPace(activity.avgPaceSecPerKm)} />

        <StatCard highlight label="Średnie HR" value={activity.avgHr ? `${Math.round(activity.avgHr)} bpm` : "—"} />
        <StatCard highlight label="Kalorie" value={activity.calories ? `${Math.round(activity.calories)} kcal` : "—"} />
        <StatCard highlight label="Kadencja" value={activity.avgCadence ? `${Math.round(activity.avgCadence)} kr/min` : "—"} />

        {activity.maxHr ? <StatCard label="Maks. HR" value={`${Math.round(activity.maxHr)} bpm`} /> : null}
        {activity.elevationGainM ? <StatCard label="Podejście" value={`${Math.round(activity.elevationGainM)} m`} /> : null}
        {activity.vo2Max ? <StatCard label="VO2max" value={`${Math.round(activity.vo2Max)}`} /> : null}
        {activity.avgGroundContactTimeMs ? (
          <StatCard label="Czas kontaktu z podłożem" value={`${Math.round(activity.avgGroundContactTimeMs)} ms`} />
        ) : null}
        {activity.avgVerticalOscillationCm ? (
          <StatCard label="Oscylacja wertykalna" value={`${activity.avgVerticalOscillationCm.toFixed(1)} cm`} />
        ) : null}
        {activity.avgVerticalRatioPct ? (
          <StatCard label="Wskaźnik wertykalny" value={`${activity.avgVerticalRatioPct.toFixed(1)}%`} />
        ) : null}
        {activity.avgStrideLengthCm ? (
          <StatCard label="Długość kroku" value={`${activity.avgStrideLengthCm.toFixed(0)} cm`} />
        ) : null}
        {activity.avgGroundContactBalanceLeftPct ? (
          <StatCard
            label="Balans kontaktu (L/P)"
            value={`${activity.avgGroundContactBalanceLeftPct.toFixed(1)}% / ${(100 - activity.avgGroundContactBalanceLeftPct).toFixed(1)}%`}
          />
        ) : null}
        {activity.avgPowerW ? <StatCard label="Moc średnia" value={`${Math.round(activity.avgPowerW)} W`} /> : null}
        {activity.maxPowerW ? <StatCard label="Moc maks." value={`${Math.round(activity.maxPowerW)} W`} /> : null}
        {activity.avgRespirationRate ? (
          <StatCard label="Częstość oddechów" value={`${activity.avgRespirationRate.toFixed(1)} /min`} />
        ) : null}
        {activity.aerobicTrainingEffect ? (
          <StatCard label="Efekt aerobowy" value={activity.aerobicTrainingEffect.toFixed(1)} />
        ) : null}
        {activity.anaerobicTrainingEffect ? (
          <StatCard label="Efekt anaerobowy" value={activity.anaerobicTrainingEffect.toFixed(1)} />
        ) : null}
      </section>

      {elevData && <ElevationChart data={elevData} syncId="run-detail" />}
      {(hrData || gcbData) && (
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
          {hrData && (
            <RunMetricChart data={hrData} label="Tętno" unit="bpm" color="var(--color-accent)" syncId="run-detail" />
          )}
          {gcbData && <GcbChart data={gcbData} syncId="run-detail" />}
        </div>
      )}

      <NotesEditor
        initialNotes={activity.notes ?? ""}
        onSave={saveRunningNotes.bind(null, activity._id.toString())}
      />

      <AiAnalysisCard
        targetType="running"
        targetId={activity._id.toString()}
        analysis={analysis ? serializeAnalysis(analysis) : null}
      />
    </div>
  );
}
