import type {
  BiomarkersResponse, MarkerGroup, Night, SleepApiResponse, SleepCycleExport,
  Week, Workout,
} from './types';

export function shapeSleep(api: SleepApiResponse, sc: SleepCycleExport): Night[] {
  const byDate = new Map<string, Night>();
  (sc.sessions || []).forEach((r) => {
    const o: Record<string, any> = Object.fromEntries(sc.fields.map((f, i) => [f, r[i]]));
    const date = String(o.end || '').slice(0, 10);
    if (!date) return;
    byDate.set(date, {
      date,
      total: o.inbed_s || o.asleep_s,
      asleep: o.asleep_s,
      deep: o.deep_s,
      rem: o.rem_s,
      light: o.light_s || (o.deep_s || o.rem_s ? 0 : o.asleep_s),
      awake: o.awake_s,
      quality: o.quality,
      hrv: null,
      hr: null,
      src: 'Sleep Cycle',
    });
  });
  (api.sessions || []).forEach((s) => {
    const date = s.ended_at.slice(0, 10);
    byDate.set(date, {
      date,
      total: s.total_seconds,
      asleep: s.sleep_seconds,
      deep: s.deep_seconds,
      rem: s.rem_seconds,
      light: s.light_seconds,
      awake: s.awake_seconds,
      quality: null,
      hrv: s.avg_hrv,
      hr: s.avg_hr,
      src: 'Eight Sleep',
    });
  });
  return [...byDate.values()].sort((a, b) => (a.date < b.date ? -1 : 1));
}

export function workoutVolume(w: Workout): { vol: number; sets: number } {
  let vol = 0;
  let sets = 0;
  (w.exercises || []).forEach((ex) =>
    (ex.sets || []).forEach((s) => {
      sets++;
      if (s.weight_kg && s.reps) vol += s.weight_kg * s.reps;
    }),
  );
  return { vol, sets };
}

export function weekStart(d: string): string {
  const dt = new Date(d);
  const day = (dt.getDay() + 6) % 7;
  dt.setDate(dt.getDate() - day);
  return dt.toISOString().slice(0, 10);
}

export function shapeWeeks(workouts: Workout[], n: number): Week[] {
  const map = new Map<string, Week>();
  workouts.forEach((w) => {
    const k = weekStart(w.start_time);
    if (!map.has(k)) map.set(k, { start: k, vol: 0, count: 0, sets: 0 });
    const e = map.get(k)!;
    const { vol, sets } = workoutVolume(w);
    e.vol += vol;
    e.count++;
    e.sets += sets;
  });
  return [...map.values()].sort((a, b) => (a.start < b.start ? -1 : 1)).slice(-n);
}

export function shapeBiomarkers(bm: BiomarkersResponse): MarkerGroup[] {
  const groups = new Map<string, typeof bm.biomarkers>();
  bm.biomarkers.forEach((b) => {
    if (!groups.has(b.name)) groups.set(b.name, []);
    groups.get(b.name)!.push(b);
  });
  const out: MarkerGroup[] = [];
  groups.forEach((hist, name) => {
    hist.sort((a, b) => (a.collected < b.collected ? -1 : 1));
    const latest = hist[hist.length - 1];
    const series = hist
      .filter((h) => h.unit === latest.unit && h.value_num != null)
      .map((h) => ({ d: h.collected, v: h.value_num! }));
    out.push({ name, latest, series, panel: latest.panel });
  });
  return out.sort((a, b) => a.name.localeCompare(b.name));
}
