import { useState, useMemo } from 'react'
import { useQuery, keepPreviousData } from '@tanstack/react-query'
import {
  AreaChart, Area, ComposedChart, Line, BarChart, Bar, ReferenceLine, ReferenceArea,
  XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell,
} from 'recharts'
import { format, subDays, differenceInCalendarDays, parseISO } from 'date-fns'
import api from '../utils/api'
import { formatSleep, sportIcon } from '../utils/format'
import { BB_INFERRED_COLOR, BB_INFERRED_LABEL, bbLevelColor, inferBBType } from '../utils/bodyBattery'
import HrvBadge from '../components/ui/HrvBadge'
import SleepHypnogram from '../components/health/SleepHypnogram'

const RANGES = [
  { label: '1W',  days: 7 },
  { label: '2W',  days: 14 },
  { label: '1M',  days: 30 },
  { label: '3M',  days: 90 },
  { label: '6M',  days: 180 },
  { label: '1Y',  days: 365 },
  { label: '3Y',  days: 1095 },
  { label: '5Y',  days: 1825 },
]

// ── VO2 Max gauge ────────────────────────────────────────────────────────────

// Garmin/Cooper Institute VO2 max thresholds
// [maxAge, [fair_min, good_min, excellent_min, superior_min]]
// value < fair_min → Poor; >= superior_min → Superior
const VO2_MALE = [
  [29, [41.7, 45.4, 51.1, 55.4]],
  [39, [40.5, 44.0, 48.3, 54.0]],
  [49, [38.5, 42.4, 46.4, 52.5]],
  [59, [35.6, 39.2, 43.4, 48.9]],
  [69, [32.3, 35.5, 39.5, 45.7]],
  [Infinity, [29.4, 32.3, 36.7, 42.1]],
]
const VO2_FEMALE = [
  [29, [36.1, 39.5, 43.9, 49.6]],
  [39, [34.4, 37.8, 42.4, 47.4]],
  [49, [33.0, 36.3, 39.7, 45.3]],
  [59, [30.1, 33.0, 36.7, 41.1]],
  [69, [27.5, 30.0, 33.0, 37.8]],
  [Infinity, [25.9, 28.1, 30.9, 36.7]],
]
const VO2_CATEGORIES = [
  { label: 'Poor',      color: '#ef4444' },
  { label: 'Fair',      color: '#f97316' },
  { label: 'Good',      color: '#22c55e' },
  { label: 'Excellent', color: '#3b82f6' },
  { label: 'Superior',  color: '#a855f7' },
]

function getVo2Category(value, age, sex) {
  const table = sex === 'female' ? VO2_FEMALE : VO2_MALE
  const row = table.find(([maxAge]) => age <= maxAge) || table[table.length - 1]
  const thresholds = row[1]
  // thresholds are lower-bounds: count how many the value meets or exceeds
  const idx = thresholds.reduce((n, t) => value >= t ? n + 1 : n, 0)
  return VO2_CATEGORIES[idx]
}

function Vo2MaxGauge({ value, birthYear, biologicalSex }) {
  const MIN = 30, MAX = 70
  // cx/cy = centre of the semicircle; arc goes left→top→right (sweep=1, clockwise in SVG)
  const cx = 70, cy = 74, r = 50, sw = 11

  const age = birthYear ? new Date().getFullYear() - birthYear : 40

  // Standard-math angle: PI = left (VO2 30), 0 = right (VO2 70)
  const toAngle = v => Math.PI * (1 - Math.max(0, Math.min(1, (v - MIN) / (MAX - MIN))))

  // SVG coordinates for a VO2 value at a given radius from centre
  const toXY = (v, radius = r) => {
    const a = toAngle(v)
    return [cx + radius * Math.cos(a), cy - radius * Math.sin(a)]
  }

  // Arc path from VO2 v1 to v2; sweep=1 → clockwise = upper semicircle in SVG
  const arc = (v1, v2, radius = r) => {
    const [x1, y1] = toXY(v1, radius)
    const [x2, y2] = toXY(v2, radius)
    const large = 0  // gauge spans 180°, so no segment ever exceeds 180°
    return `M ${x1.toFixed(2)} ${y1.toFixed(2)} A ${radius} ${radius} 0 ${large} 1 ${x2.toFixed(2)} ${y2.toFixed(2)}`
  }

  // ACSM category boundaries for this user's age/sex
  const table = biologicalSex === 'female' ? VO2_FEMALE : VO2_MALE
  const row = table.find(([maxAge]) => age <= maxAge) || table[table.length - 1]
  const thresholds = row[1]
  const bounds = [MIN, ...thresholds, MAX]   // 6 boundary values for 5 colour bands

  const cat = value != null ? getVo2Category(value, age, biologicalSex) : null

  // White arrow: tip lands exactly at the arc centre-line at the value's angle;
  // base extends outside the track — unambiguously marks the precise position.
  const arrowPts = value != null ? (() => {
    const a = toAngle(Math.max(MIN, Math.min(MAX, value)))
    const tipR  = r                  // tip at centre of the coloured track
    const baseR = r + sw / 2 + 9    // base well outside the outer edge
    const s = 0.09                   // half-spread ≈ 5° — narrow for precision
    const tipX = cx + tipR  * Math.cos(a),  tipY = cy - tipR  * Math.sin(a)
    const b1x  = cx + baseR * Math.cos(a + s), b1y = cy - baseR * Math.sin(a + s)
    const b2x  = cx + baseR * Math.cos(a - s), b2y = cy - baseR * Math.sin(a - s)
    return `${tipX.toFixed(1)},${tipY.toFixed(1)} ${b1x.toFixed(1)},${b1y.toFixed(1)} ${b2x.toFixed(1)},${b2y.toFixed(1)}`
  })() : null

  return (
    <div className="flex flex-col items-center">
      <svg width="140" height="92" viewBox="0 0 140 92">
        {/* Dark background track, slightly wider than the colour bands */}
        <path d={arc(MIN, MAX)} stroke="#1f2937" strokeWidth={sw + 4} fill="none" strokeLinecap="butt" />

        {/* Full-brightness ACSM colour bands */}
        {VO2_CATEGORIES.map((c, i) => {
          const v1 = Math.max(bounds[i], MIN)
          const v2 = Math.min(bounds[i + 1], MAX)
          if (v2 <= v1) return null
          return (
            <path key={i} d={arc(v1, v2)}
              stroke={c.color} strokeWidth={sw} fill="none" strokeLinecap="butt" />
          )
        })}

        {/* White arrow: tip at exact value position on arc, base pointing outward */}
        {arrowPts && <polygon points={arrowPts} fill="white" />}

        {/* VO2 number, coloured by category */}
        <text x={cx} y={cy - 6} textAnchor="middle" dominantBaseline="middle"
          fontSize="21" fontWeight="700" fill={cat?.color ?? '#6b7280'}>
          {value != null ? value.toFixed(1) : '--'}
        </text>

        {/* Category label */}
        <text x={cx} y={cy + 11} textAnchor="middle" dominantBaseline="middle"
          fontSize="9" fill="#9ca3af">
          {cat?.label ?? (biologicalSex ? '' : 'Set sex in profile')}
        </text>
      </svg>
    </div>
  )
}

const tooltipStyle = {
  background: '#111827', border: '1px solid #374151', borderRadius: 8, fontSize: 12,
}

// Normalise any date string to YYYY-MM-DD so XAxis values and ReferenceLine x match.
const d10 = (s) => (s || '').slice(0, 10)

// ── Daily Snapshot ──────────────────────────────────────────────────────────

function fmtTime(ts) {
  if (!ts) return '--'
  return new Date(ts).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })
}

function IntradayHrChart({ values }) {
  if (!values?.length) return null
  const data = values.map(([ts, hr]) => ({ t: ts, hr }))
  return (
    <ResponsiveContainer width="100%" height={100}>
      <AreaChart data={data} margin={{ top: 4, right: 4, bottom: 0, left: 0 }}>
        <defs>
          <linearGradient id="grad-intraday-hr" x1="0" y1="0" x2="0" y2="1">
            <stop offset="5%"  stopColor="#f43f5e" stopOpacity={0.3} />
            <stop offset="95%" stopColor="#f43f5e" stopOpacity={0} />
          </linearGradient>
        </defs>
        <XAxis dataKey="t" tick={{ fontSize: 9, fill: '#6b7280' }} axisLine={false} tickLine={false}
          tickFormatter={ts => format(new Date(ts), 'HH:mm')}
          interval={Math.max(1, Math.floor(data.length / 6))} />
        <YAxis tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false} width={28}
          tickFormatter={v => Math.round(v)} domain={['auto', 'auto']} />
        <Tooltip contentStyle={tooltipStyle}
          labelFormatter={ts => format(new Date(ts), 'HH:mm')}
          formatter={v => [`${Math.round(v)} bpm`, 'HR']} />
        <Area type="monotone" dataKey="hr" stroke="#f43f5e" strokeWidth={1.5}
          fill="url(#grad-intraday-hr)" dot={false} isAnimationActive={false} connectNulls={false} />
      </AreaChart>
    </ResponsiveContainer>
  )
}

// ── Body Battery ─────────────────────────────────────────────────────────────

function ActivityRefLabel({ viewBox, icon }) {
  if (!viewBox) return null
  const { x, y, width = 0 } = viewBox
  return (
    <text x={x + width / 2} y={y + 12} textAnchor="middle" fontSize={14} fill="white" style={{ pointerEvents: 'none' }}>
      {icon}
    </text>
  )
}

function BodyBatteryChart({ bb, hiresValues, sleepStart, sleepEnd, activities }) {
  if (!bb) return null
  const { charged, drained, start_level, end_level } = bb
  if (!hiresValues?.length && !bb.values?.length && end_level == null) return null

  const rawData = hiresValues?.length
    ? hiresValues.map(([ts, level]) => ({ t: ts, level }))
    : (bb.values || []).map(([ts, level]) => ({ t: ts, level }))

  if (!rawData.length) return null

  const sleepStartMs = sleepStart ? new Date(sleepStart).getTime() : null
  const sleepEndMs   = sleepEnd   ? new Date(sleepEnd).getTime()   : null

  const chartData = rawData.map((d, i) => ({
    ...d,
    type: inferBBType(d.t, d.level, i > 0 ? rawData[i - 1].level : null, sleepStartMs, sleepEndMs),
  }))

  const presentTypes = [...new Set(chartData.map(d => d.type))]
  const levelColor = bbLevelColor(end_level)
  const maxLevel = chartData.length ? Math.max(...chartData.map(d => d.level)) : null

  // The X axis is categorical (band scale), so overlays must use values that
  // exist in the data — snap activity start/end to the nearest sample.
  const nearestT = (ms) => {
    let best = null, bd = Infinity
    for (const d of chartData) { const dd = Math.abs(d.t - ms); if (dd < bd) { bd = dd; best = d.t } }
    return best
  }

  return (
    <div className="bg-gray-900 rounded-xl border border-gray-800 p-4 flex flex-col h-full">
      <h3 className="text-sm font-medium text-gray-300 mb-2">Body Battery</h3>

      <div className="flex items-baseline gap-3 flex-wrap mb-3">
        {maxLevel != null && (
          <span className="text-3xl font-bold" style={{ color: bbLevelColor(maxLevel) }}>{Math.round(maxLevel)}</span>
        )}
        {charged != null && (
          <span className="text-sm font-semibold text-green-400">+{charged}</span>
        )}
        {drained != null && (
          <span className="text-sm font-semibold text-orange-400">-{drained}</span>
        )}
        {end_level != null && (
          <span className="text-xs text-gray-500">now {Math.round(end_level)}</span>
        )}
      </div>

      <div className="flex-1">
        <ResponsiveContainer width="100%" height={100}>
          <BarChart data={chartData} margin={{ top: 2, right: 4, bottom: 0, left: 28 }} barCategoryGap={0}>
            <XAxis dataKey="t" tick={{ fontSize: 9, fill: '#6b7280' }} axisLine={false} tickLine={false}
              tickFormatter={ts => format(new Date(ts), 'HH:mm')}
              interval={Math.max(1, Math.floor(chartData.length / 6))} />
            <YAxis domain={[0, 100]} tick={{ fontSize: 9, fill: '#6b7280' }} axisLine={false} tickLine={false} width={28}
              tickFormatter={v => v} ticks={[0, 25, 50, 75, 100]} />
            <Tooltip contentStyle={tooltipStyle} itemStyle={{ color: '#fff' }} labelStyle={{ color: '#fff' }}
              labelFormatter={ts => format(new Date(ts), 'HH:mm')}
              formatter={v => [`${Math.round(v)}%`, 'Battery']} />
            <Bar dataKey="level" isAnimationActive={false} radius={0}>
              {chartData.map((d, i) => (
                <Cell key={i} fill={BB_INFERRED_COLOR[d.type]} />
              ))}
            </Bar>
            {(activities || []).map(a => {
              const start = new Date(a.start_time).getTime()
              const end = a.duration_s ? start + a.duration_s * 1000 : start
              const x1 = nearestT(start), x2 = nearestT(end)
              if (x1 == null || x2 == null) return null
              return (
                <ReferenceArea
                  key={`area-${a.id}`}
                  x1={x1}
                  x2={x2}
                  fill="rgba(255,255,255,0.16)"
                  stroke="rgba(255,255,255,0.3)"
                  strokeWidth={1}
                  label={<ActivityRefLabel icon={sportIcon(a.sport_type)} />}
                />
              )
            })}
          </BarChart>
        </ResponsiveContainer>
      </div>

      <div className="flex flex-wrap gap-x-3 gap-y-1 mt-2">
        {presentTypes.map(type => (
          <div key={type} className="flex items-center gap-1">
            <div className="w-2 h-2 rounded-sm" style={{ backgroundColor: BB_INFERRED_COLOR[type] }} />
            <span className="text-xs text-gray-500">{BB_INFERRED_LABEL[type]}</span>
          </div>
        ))}
      </div>
    </div>
  )
}

function SleepStageFallbackBar({ deepS, remS, lightS, awakeS }) {
  const total = (deepS || 0) + (remS || 0) + (lightS || 0) + (awakeS || 0)
  if (!total) return null
  const segments = [
    { label: 'Deep',  s: deepS  || 0, color: '#6366f1' },
    { label: 'REM',   s: remS   || 0, color: '#7c3aed' },
    { label: 'Light', s: lightS || 0, color: '#a78bfa' },
    { label: 'Awake', s: awakeS || 0, color: '#eab308' },
  ].filter(seg => seg.s > 0)
  return (
    <div className="mt-2">
      <div className="flex h-5 rounded-sm overflow-hidden">
        {segments.map(seg => (
          <div key={seg.label} style={{ width: `${(seg.s / total) * 100}%`, backgroundColor: seg.color }} />
        ))}
      </div>
    </div>
  )
}

function NavArrow({ onClick, disabled, children }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className="w-7 h-7 flex items-center justify-center rounded-lg text-gray-400
                 hover:text-white hover:bg-gray-800 disabled:opacity-20 disabled:cursor-default
                 transition-colors text-base font-medium"
    >
      {children}
    </button>
  )
}

function DailySnapshot({ day, snapshotWeight, avg30, intradayHr, bodyBattery, bbHires, sleepStages, activities, latestVo2max, birthYear, biologicalSex, onOlder, onNewer, hasOlder, hasNewer }) {
  if (!day) return (
    <div className="text-center py-10 text-gray-600">
      <p className="text-3xl mb-2">📊</p>
      <p>No health data yet</p>
      <p className="text-sm mt-1">Import a Garmin export to see your daily snapshot</p>
    </div>
  )

  const dateLabel = day.date ? format(new Date(day.date), 'EEEE, d MMMM yyyy') : 'Latest'
  const hasSleepStages = day.sleep_deep_s || day.sleep_light_s || day.sleep_rem_s
  const stepsGoal = 10000
  const stepsPct = day.steps ? Math.min(100, Math.round(day.steps / stepsGoal * 100)) : 0

  const stressLabel = !day.avg_stress ? null
    : day.avg_stress < 25 ? 'Restful'
    : day.avg_stress < 50 ? 'Low'
    : day.avg_stress < 75 ? 'Medium' : 'High'
  const stressColor = !day.avg_stress ? 'text-white'
    : day.avg_stress < 25 ? 'text-green-400'
    : day.avg_stress < 50 ? 'text-yellow-400'
    : day.avg_stress < 75 ? 'text-orange-400' : 'text-red-400'

  return (
    <div className="space-y-4">

      {/* Header + arrows */}
      <div className="flex items-center gap-3">
        <NavArrow onClick={onOlder} disabled={!hasOlder}>←</NavArrow>
        <div className="min-w-0">
          <p className="text-xs text-gray-500 uppercase tracking-wide">Daily snapshot</p>
          <h2 className="text-xl font-semibold text-white leading-tight">{dateLabel}</h2>
        </div>
        <NavArrow onClick={onNewer} disabled={!hasNewer}>→</NavArrow>
      </div>

      {/* Sleep (wide) + Heart / HRV */}
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">

        <div className="bg-gray-900 rounded-xl border border-gray-800 p-5 space-y-3">
          <div className="flex items-center justify-between">
            <h3 className="text-sm font-medium text-gray-300">Sleep</h3>
            {day.sleep_score != null && (
              <span className="text-xs px-2 py-0.5 rounded-full border border-indigo-400/30 bg-indigo-400/10 text-indigo-300">
                Score {Math.round(day.sleep_score)}
              </span>
            )}
          </div>
          <div className="flex flex-wrap items-end gap-3">
            <span className="text-4xl font-bold text-white tracking-tight">
              {formatSleep(day.sleep_duration_s)}
            </span>
            {day.sleep_start && day.sleep_end && (
              <span className="text-sm text-gray-500 pb-1">
                {fmtTime(day.sleep_start)} → {fmtTime(day.sleep_end)}
              </span>
            )}
          </div>
          {hasSleepStages ? (
            <>
              {sleepStages?.length ? (
                <SleepHypnogram
                  sleepStart={day.sleep_start} sleepEnd={day.sleep_end}
                  stages={sleepStages}
                />
              ) : (
                <SleepStageFallbackBar
                  deepS={day.sleep_deep_s} remS={day.sleep_rem_s}
                  lightS={day.sleep_light_s} awakeS={day.sleep_awake_s}
                />
              )}
              <div className="flex flex-wrap gap-x-5 gap-y-1.5 mt-2">
                {[
                  ['Deep',  day.sleep_deep_s,  '#6366f1'],
                  ['REM',   day.sleep_rem_s,   '#7c3aed'],
                  ['Light', day.sleep_light_s, '#a78bfa'],
                  ['Awake', day.sleep_awake_s, '#eab308'],
                ].map(([label, secs, color]) => secs ? (
                  <div key={label} className="flex items-center gap-1.5">
                    <div className="w-2.5 h-2.5 rounded-sm" style={{ backgroundColor: color }} />
                    <span className="text-xs text-gray-400">
                      {label} <span className="text-white">{formatSleep(secs)}</span>
                    </span>
                  </div>
                ) : null)}
              </div>
            </>
          ) : !day.sleep_duration_s ? (
            <p className="text-sm text-gray-600">No sleep data</p>
          ) : null}
        </div>

        <div className="bg-gray-900 rounded-xl border border-gray-800 p-5">
          <h3 className="text-sm font-medium text-gray-300 mb-3">Heart & HRV</h3>
          <div className="grid grid-cols-2 gap-x-4 gap-y-3">
            <div>
              <p className="text-xs text-gray-500 mb-0.5">Resting HR</p>
              <div className="flex items-baseline gap-1.5">
                <span className="text-3xl font-bold text-rose-400">
                  {day.resting_hr ? Math.round(day.resting_hr) : '--'}
                </span>
                <span className="text-sm text-gray-500">bpm</span>
              </div>
              {avg30?.resting_hr && day.resting_hr && (
                <p className="text-xs text-gray-500 mt-0.5">
                  30d avg {Math.round(avg30.resting_hr)}
                  {day.resting_hr < avg30.resting_hr
                    ? <span className="text-green-400 ml-1">↓</span>
                    : day.resting_hr > avg30.resting_hr
                    ? <span className="text-red-400 ml-1">↑</span>
                    : null}
                </p>
              )}
            </div>
            <div>
              <p className="text-xs text-gray-500 mb-0.5">HRV</p>
              <div className="flex items-baseline gap-1.5 flex-wrap">
                <span className="text-3xl font-bold text-violet-400">
                  {(day.hrv_weekly_avg ?? day.hrv_nightly_avg) ? Math.round(day.hrv_weekly_avg ?? day.hrv_nightly_avg) : '--'}
                </span>
                <span className="text-sm text-gray-500">ms</span>
              </div>
              <div className="mt-0.5"><HrvBadge status={day.hrv_status} /></div>
            </div>
            <div>
              <p className="text-xs text-gray-500 mb-0.5">Avg HR (day)</p>
              <div className="flex items-baseline gap-1.5">
                <span className="text-xl font-semibold text-orange-400">
                  {day.avg_hr_day ? Math.round(day.avg_hr_day) : '--'}
                </span>
                {day.max_hr_day && <span className="text-xs text-gray-500">/ {Math.round(day.max_hr_day)} max</span>}
              </div>
            </div>
            <div>
              <p className="text-xs text-gray-500 mb-0.5">Weight</p>
              <div className="flex items-baseline gap-1.5 flex-wrap">
                <span className="text-xl font-semibold text-emerald-400">
                  {snapshotWeight ? snapshotWeight.kg.toFixed(1) : '--'}
                </span>
                {snapshotWeight && <span className="text-xs text-gray-500">kg</span>}
                {snapshotWeight?.fat && !snapshotWeight.carried && <span className="text-xs text-gray-500">{snapshotWeight.fat.toFixed(1)}% fat</span>}
              </div>
              {snapshotWeight?.carried && (
                <p className="text-xs text-gray-600 mt-0.5">as of {format(new Date(snapshotWeight.date), 'd MMM')}</p>
              )}
            </div>
          </div>
        </div>
      </div>

      {/* 24-hour heart rate chart + body battery (side by side) */}
      {(intradayHr?.length > 0 || bodyBattery) && (
        <div className={`grid gap-4 ${intradayHr?.length > 0 && bodyBattery ? 'grid-cols-1 lg:grid-cols-2' : 'grid-cols-1'}`}>
          {intradayHr?.length > 0 && (
            <div className="bg-gray-900 rounded-xl border border-gray-800 p-4 flex flex-col">
              <div className="flex items-center justify-between mb-2">
                <h3 className="text-sm font-medium text-gray-300">24-hour Heart Rate</h3>
                {day.avg_hr_day && (
                  <span className="text-xs text-gray-500">avg {Math.round(day.avg_hr_day)} bpm</span>
                )}
              </div>
              <div className="flex-1 min-h-0">
                <IntradayHrChart values={intradayHr} />
              </div>
            </div>
          )}
          <BodyBatteryChart bb={bodyBattery} hiresValues={bbHires} sleepStart={day?.sleep_start} sleepEnd={day?.sleep_end} activities={activities} />
        </div>
      )}

      {/* Activity strip */}
      <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">

        <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
          <p className="text-xs text-gray-500 mb-1">Steps</p>
          <div className="flex items-baseline gap-1 mb-2">
            <span className="text-2xl font-bold text-yellow-400">
              {day.steps ? day.steps.toLocaleString() : '--'}
            </span>
          </div>
          {day.steps ? (
            <>
              <div className="h-1.5 bg-gray-800 rounded-full overflow-hidden">
                <div className="h-full bg-yellow-400 rounded-full transition-all"
                  style={{ width: `${stepsPct}%` }} />
              </div>
              <p className="text-xs text-gray-600 mt-1">{stepsPct}% of {stepsGoal.toLocaleString()}</p>
            </>
          ) : null}
          {day.floors_climbed
            ? <p className="text-xs text-gray-500 mt-1">{day.floors_climbed} floors</p>
            : null}
        </div>

        <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
          <p className="text-xs text-gray-500 mb-1">Calories</p>
          <div className="flex items-baseline gap-1">
            <span className="text-2xl font-bold text-white">
              {day.total_calories
                ? Math.round(day.total_calories)
                : day.active_calories ? Math.round(day.active_calories) : '--'}
            </span>
            <span className="text-xs text-gray-500">kcal</span>
          </div>
          {day.active_calories && day.total_calories && (
            <p className="text-xs text-gray-500 mt-1">Active {Math.round(day.active_calories)} kcal</p>
          )}
        </div>

        <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
          <p className="text-xs text-gray-500 mb-1">Stress</p>
          <div className="flex items-baseline gap-1">
            <span className={`text-2xl font-bold ${stressColor}`}>
              {day.avg_stress ? Math.round(day.avg_stress) : '--'}
            </span>
            {day.avg_stress && <span className="text-xs text-gray-500">/100</span>}
          </div>
          {stressLabel && <p className="text-xs text-gray-500 mt-1">{stressLabel}</p>}
        </div>

        <div className="bg-gray-900 rounded-xl border border-gray-800 p-4 flex flex-col">
          <p className="text-xs text-gray-500 mb-1">VO2 Max</p>
          <div className="flex-1 flex items-center justify-center">
            <Vo2MaxGauge
              value={(day.vo2max ?? latestVo2max) ?? null}
              birthYear={birthYear}
              biologicalSex={biologicalSex}
            />
          </div>
          {day.fitness_age && <p className="text-xs text-gray-500 mt-1 text-center">Fitness age {day.fitness_age}</p>}
        </div>
      </div>
    </div>
  )
}

// ── Trend Charts ────────────────────────────────────────────────────────────

// Highlight problem days on a trend line by colouring the dot from a status field
// (e.g. HRV status): orange = unbalanced, red = low/poor. Other days get no dot.
const STATUS_DOT_COLORS = { balanced: '#22c55e', unbalanced: '#f97316', low: '#ef4444', poor: '#ef4444' }
const statusDot = (statusKey) => (props) => {
  const { cx, cy, payload } = props
  const color = STATUS_DOT_COLORS[String(payload?.[statusKey] || '').toLowerCase()]
  if (cx == null || cy == null || !color) return null
  return <circle cx={cx} cy={cy} r={3.5} fill={color} stroke="#111827" strokeWidth={1} />
}

// Custom tooltip: collapses the dashed gap-bridging Line and the solid Area
// (same dataKey) into one row, and never shows the helper baseline band.
function ChartTooltip({ active, payload, label, formatter }) {
  if (!active || !payload?.length) return null
  const seen = new Set()
  const rows = []
  for (const p of payload) {
    if (p.dataKey === '__band' || p.value == null || seen.has(p.dataKey)) continue
    seen.add(p.dataKey)
    rows.push(p)
  }
  if (!rows.length) return null
  return (
    <div style={{ ...tooltipStyle, padding: '6px 10px' }}>
      <div style={{ color: '#9ca3af', marginBottom: 2 }}>{format(new Date(label), 'MMM d, yyyy')}</div>
      {rows.map(p => (
        <div key={p.dataKey} style={{ color: '#fff' }}>{formatter ? formatter(p.value) : p.value?.toFixed(1)}</div>
      ))}
    </div>
  )
}

function MetricChart({ data, dataKey, color, formatter, height = 140, selectedDate, onDayClick, connectNulls = false, showDots = false, domain, referenceLines, statusDotKey, bandLowKey, bandHighKey, bandColor = '#9ca3af' }) {
  const vals = data.filter(d => d[dataKey] != null)
  if (!vals.length) return (
    <div className="flex items-center justify-center text-gray-600 text-xs" style={{ height }}>No data</div>
  )
  // Range band (e.g. Garmin's HRV baseline): Recharts renders an Area as a band
  // when its dataKey resolves to a [low, high] pair.
  const hasBand = bandLowKey && bandHighKey
  const chartData = hasBand
    ? data.map(d => ({
        ...d,
        __band: (d[bandLowKey] != null && d[bandHighKey] != null) ? [d[bandLowKey], d[bandHighKey]] : null,
      }))
    : data
  return (
    <ResponsiveContainer width="100%" height={height}>
      <ComposedChart
        data={chartData}
        margin={{ top: 4, right: 4, bottom: 4, left: 0 }}
        style={{ cursor: onDayClick ? 'pointer' : 'default' }}
        onClick={evt => {
          const p = evt?.activePayload?.[0]?.payload
          if (p?.date && onDayClick) onDayClick(p.date)
        }}
      >
        <defs>
          <linearGradient id={`grad-${dataKey}`} x1="0" y1="0" x2="0" y2="1">
            <stop offset="5%" stopColor={color} stopOpacity={0.3} />
            <stop offset="95%" stopColor={color} stopOpacity={0} />
          </linearGradient>
        </defs>
        <CartesianGrid strokeDasharray="3 3" stroke="#1f2937" vertical={false} />
        <XAxis dataKey="date" tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false}
          tickFormatter={d => format(new Date(d), 'MMM d')} interval="preserveStartEnd" />
        <YAxis tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false} width={36}
          tickFormatter={formatter} domain={domain} />
        <Tooltip content={<ChartTooltip formatter={formatter} />} />
        {hasBand && (
          <Area type="monotone" dataKey="__band" stroke="none" fill={bandColor} fillOpacity={0.18}
            connectNulls isAnimationActive={false} legendType="none" activeDot={false} />
        )}
        {selectedDate && (
          <ReferenceLine x={selectedDate} stroke="#60a5fa" strokeWidth={1.5} strokeDasharray="4 2" />
        )}
        {(referenceLines || []).map((rl, i) => (
          <ReferenceLine key={i} {...rl} />
        ))}
        {/* Dashed line bridging gaps (no data). Drawn first; the solid area below
            covers it wherever real data exists, leaving only gaps shown dashed. */}
        <Line type="monotone" dataKey={dataKey} stroke={color} strokeWidth={1.5}
          strokeDasharray="4 4" dot={false} connectNulls isAnimationActive={false} legendType="none" />
        <Area type="monotone" dataKey={dataKey} stroke={color} strokeWidth={2}
          fill={`url(#grad-${dataKey})`}
          dot={statusDotKey ? statusDot(statusDotKey) : (showDots ? { fill: color, r: 3, strokeWidth: 0 } : false)}
          connectNulls={false} isAnimationActive={false} />
      </ComposedChart>
    </ResponsiveContainer>
  )
}

function SleepChart({ data, selectedDate, onDayClick }) {
  const chartData = data.map(d => ({
    date: d.date,   // already normalised to YYYY-MM-DD
    deep:  d.sleep_deep_s  ? +(d.sleep_deep_s  / 3600).toFixed(2) : null,
    rem:   d.sleep_rem_s   ? +(d.sleep_rem_s   / 3600).toFixed(2) : null,
    light: d.sleep_light_s ? +(d.sleep_light_s / 3600).toFixed(2) : null,
    awake: d.sleep_awake_s ? +(d.sleep_awake_s / 3600).toFixed(2) : null,
  }))
  const hasData = chartData.some(d => d.deep || d.rem || d.light)
  if (!hasData) return (
    <div className="flex items-center justify-center h-36 text-gray-600 text-xs">No sleep data</div>
  )
  const totals = chartData
    .map(d => (d.deep || 0) + (d.rem || 0) + (d.light || 0) + (d.awake || 0))
    .filter(t => t > 0)
  const avgSleep = totals.length ? +(totals.reduce((a, b) => a + b, 0) / totals.length).toFixed(1) : null
  return (
    <ResponsiveContainer width="100%" height={140}>
      <BarChart
        data={chartData}
        margin={{ top: 4, right: 44, bottom: 4, left: 0 }}
        barSize={6}
        style={{ cursor: onDayClick ? 'pointer' : 'default' }}
        onClick={evt => {
          const p = evt?.activePayload?.[0]?.payload
          if (p?.date && onDayClick) onDayClick(p.date)
        }}
      >
        <CartesianGrid strokeDasharray="3 3" stroke="#1f2937" vertical={false} />
        <XAxis dataKey="date" tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false}
          tickFormatter={d => format(new Date(d), 'MMM d')} interval="preserveStartEnd" />
        <YAxis tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false} width={24}
          tickFormatter={v => `${v}h`} />
        <Tooltip contentStyle={tooltipStyle} labelFormatter={d => format(new Date(d), 'MMM d, yyyy')} />
        {selectedDate && (
          <ReferenceLine x={selectedDate} stroke="#60a5fa" strokeWidth={1.5} strokeDasharray="4 2" />
        )}
        <ReferenceLine y={8} stroke="#22c55e" strokeDasharray="4 3" strokeWidth={1.5}
          label={{ value: '8h', position: 'right', fill: '#22c55e', fontSize: 9 }} />
        {avgSleep != null && (
          <ReferenceLine y={avgSleep} stroke="#a855f7" strokeDasharray="4 3" strokeWidth={1.5}
            label={{ value: `avg ${avgSleep}h`, position: 'right', fill: '#a855f7', fontSize: 9 }} />
        )}
        <Bar dataKey="deep"  name="Deep"  stackId="a" fill="#6366f1" />
        <Bar dataKey="rem"   name="REM"   stackId="a" fill="#7c3aed" />
        <Bar dataKey="light" name="Light" stackId="a" fill="#a78bfa" />
        <Bar dataKey="awake" name="Awake" stackId="a" fill="#eab308" radius={[2, 2, 0, 0]} />
      </BarChart>
    </ResponsiveContainer>
  )
}

// ── Weight (with goal line + kg ⇄ st/lb toggle) ──────────────────────────────

const KG_TO_LB = 2.2046226218

function fmtStLb(lb) {
  let st = Math.floor(lb / 14)
  let r = Math.round(lb - st * 14)
  if (r === 14) { st += 1; r = 0 }
  return `${st} st ${r} lb`
}

function WeightChart({ data, goalKg, selectedDate, onDayClick }) {
  const [unit, setUnit] = useState(() => localStorage.getItem('weightUnit') || 'kg')
  const choose = (u) => { setUnit(u); localStorage.setItem('weightUnit', u) }
  const imperial = unit === 'lb'
  const toU = (kg) => (imperial ? kg * KG_TO_LB : kg)

  const withWeight = data.filter(d => d.weight_kg != null)
  const series = withWeight.map(d => ({ date: d.date, w: +toU(d.weight_kg).toFixed(2) }))

  const title = imperial ? 'Weight (st & lb)' : 'Weight (kg)'
  const toggle = (
    <div className="flex gap-1">
      {[['kg', 'kg'], ['lb', 'st/lb']].map(([u, label]) => (
        <button key={u} onClick={() => choose(u)}
          className={`text-xs px-2 py-0.5 rounded-full transition-colors ${
            unit === u ? 'bg-blue-600 text-white' : 'text-gray-400 bg-gray-800 hover:text-white'
          }`}>
          {label}
        </button>
      ))}
    </div>
  )

  if (!series.length) {
    return (
      <>
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-sm font-medium text-gray-300">{title}</h3>{toggle}
        </div>
        <div className="flex items-center justify-center h-36 text-gray-600 text-xs">No weight data</div>
      </>
    )
  }

  const maxKg = Math.max(...withWeight.map(d => d.weight_kg))
  const minKg = Math.min(...withWeight.map(d => d.weight_kg))
  const goalU = goalKg != null ? +toU(goalKg).toFixed(1) : null
  const yMax = Math.ceil(toU(maxKg + 20))                       // highest weight + 20 kg equivalent
  const yMin = Math.max(0, Math.floor(toU(Math.max(0, minKg - 20))))  // lowest weight − 20 kg equivalent
  const fmtVal = (v) => (imperial ? `${fmtStLb(v)} (${Math.round(v)} lb)` : `${v.toFixed(1)} kg`)

  return (
    <>
      <div className="flex items-center justify-between mb-3">
        <h3 className="text-sm font-medium text-gray-300">{title}</h3>{toggle}
      </div>
      <ResponsiveContainer width="100%" height={140}>
        <AreaChart data={series} margin={{ top: 4, right: 4, bottom: 4, left: 0 }}
          style={{ cursor: onDayClick ? 'pointer' : 'default' }}
          onClick={evt => {
            const p = evt?.activePayload?.[0]?.payload
            if (p?.date && onDayClick) onDayClick(p.date)
          }}>
          <defs>
            <linearGradient id="grad-weight" x1="0" y1="0" x2="0" y2="1">
              <stop offset="5%" stopColor="#34d399" stopOpacity={0.3} />
              <stop offset="95%" stopColor="#34d399" stopOpacity={0} />
            </linearGradient>
          </defs>
          <CartesianGrid strokeDasharray="3 3" stroke="#1f2937" vertical={false} />
          <XAxis dataKey="date" tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false}
            tickFormatter={d => format(new Date(d), 'MMM d')} interval="preserveStartEnd" />
          <YAxis domain={[yMin, yMax]} tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false}
            width={36} tickFormatter={v => Math.round(v)} />
          <Tooltip contentStyle={tooltipStyle} labelFormatter={d => format(new Date(d), 'MMM d, yyyy')}
            formatter={v => [fmtVal(v), 'Weight']} />
          {selectedDate && (
            <ReferenceLine x={selectedDate} stroke="#60a5fa" strokeWidth={1.5} strokeDasharray="4 2" />
          )}
          {goalU != null && (
            <ReferenceLine y={goalU} stroke="#22c55e" strokeDasharray="5 3" strokeWidth={1.5}
              label={{ value: `Goal ${imperial ? fmtStLb(goalU) : `${goalU} kg`}`, position: 'insideTopLeft', fill: '#22c55e', fontSize: 9 }} />
          )}
          <Area type="monotone" dataKey="w" stroke="#34d399" strokeWidth={2}
            fill="url(#grad-weight)" dot={{ fill: '#34d399', r: 3, strokeWidth: 0 }}
            connectNulls isAnimationActive={false} />
        </AreaChart>
      </ResponsiveContainer>
    </>
  )
}

// ── Page ─────────────────────────────────────────────────────────────────────

export default function HealthPage() {
  const [rangeDays, setRangeDays] = useState(7)
  const [selectedDateStr, setSelectedDateStr] = useState(null)   // YYYY-MM-DD or null = latest

  const fromDate = useMemo(
    () => format(subDays(new Date(), rangeDays), 'yyyy-MM-dd'),
    [rangeDays],
  )

  const { data: summary } = useQuery({
    queryKey: ['health-summary'],
    queryFn: () => api.get('/health-metrics/summary').then(r => r.data),
  })

  const { data: profile } = useQuery({
    queryKey: ['profile'],
    queryFn: () => api.get('/profile/').then(r => r.data),
  })

  // Full history for snapshot navigation.
  // Key starts with ['health-metrics'] so UploadPage invalidation hits it automatically.
  const { data: allDays } = useQuery({
    queryKey: ['health-metrics', 'all'],
    queryFn: () =>
      api.get('/health-metrics/', { params: { limit: 2000 } })
        .then(r => r.data.map(d => ({ ...d, date: d10(d.date) }))),
  })

  // Trend window (changes with range selector).
  // Dates normalised to YYYY-MM-DD so XAxis values match ReferenceLine x.
  const { data: rawMetrics, isLoading } = useQuery({
    queryKey: ['health-metrics', rangeDays],
    queryFn: () =>
      api.get('/health-metrics/', { params: { from_date: fromDate, limit: rangeDays + 1 } })
        .then(r => r.data.slice().reverse().map(d => ({ ...d, date: d10(d.date) }))),
    placeholderData: keepPreviousData,
  })
  const metrics = rawMetrics || []

  // Snapshot navigation: newest-first sorted list of all available days
  const allDaysSorted = useMemo(
    () => (allDays || []).slice().sort((a, b) => b.date.localeCompare(a.date)),
    [allDays],
  )

  // Disable trend ranges that reach further back than the data goes. Keep every
  // range up to and including the first one that already covers the full history
  // enabled; ranges beyond that would only show the same (full) data. While the
  // history is still loading we leave all ranges enabled.
  const maxEnabledRangeIdx = useMemo(() => {
    if (!allDaysSorted.length) return RANGES.length - 1
    const oldest = allDaysSorted[allDaysSorted.length - 1].date
    const span = differenceInCalendarDays(new Date(), parseISO(oldest))
    const idx = RANGES.findIndex(r => r.days >= span)
    return idx === -1 ? RANGES.length - 1 : idx
  }, [allDaysSorted])

  const selectedDay = useMemo(() => {
    if (!selectedDateStr) return allDaysSorted[0] || null
    return allDaysSorted.find(d => d.date === selectedDateStr) || null
  }, [selectedDateStr, allDaysSorted])

  const selectedIdx = useMemo(() => {
    if (!selectedDay) return -1
    return allDaysSorted.findIndex(d => d.date === selectedDay.date)
  }, [selectedDay, allDaysSorted])

  // Most recent day with a VO2 max reading (Garmin only updates it after certain activities)
  const latestVo2max = useMemo(() => {
    const found = allDaysSorted.find(d => d.vo2max != null)
    return found ? found.vo2max : null
  }, [allDaysSorted])

  // Weight for the snapshot: the selected day's, or the most recent earlier reading.
  const snapshotWeight = useMemo(() => {
    if (!selectedDay) return null
    if (selectedDay.weight_kg != null)
      return { kg: selectedDay.weight_kg, fat: selectedDay.body_fat_pct, carried: false }
    const earlier = allDaysSorted.find(d => d.weight_kg != null && d.date <= selectedDay.date)
    return earlier ? { kg: earlier.weight_kg, fat: earlier.body_fat_pct, carried: true, date: earlier.date } : null
  }, [selectedDay, allDaysSorted])

  const { data: intradayData } = useQuery({
    queryKey: ['health-intraday', selectedDay?.date],
    queryFn: () => api.get('/health-metrics/intraday', { params: { date: selectedDay.date } }).then(r => r.data),
    enabled: !!selectedDay?.date,
  })

  const { data: dayActivities } = useQuery({
    queryKey: ['activities-day', selectedDay?.date],
    queryFn: () => api.get('/activities/', { params: {
      from_date: selectedDay.date + 'T00:00:00',
      to_date:   selectedDay.date + 'T23:59:59',
      per_page: 20,
    }}).then(r => r.data),
    enabled: !!selectedDay?.date,
  })

  const handleDayClick = (dateStr) => setSelectedDateStr(d10(dateStr))
  const goOlder = () => {
    if (selectedIdx < allDaysSorted.length - 1)
      setSelectedDateStr(allDaysSorted[selectedIdx + 1].date)
  }
  const goNewer = () => {
    if (selectedIdx > 0)
      setSelectedDateStr(allDaysSorted[selectedIdx - 1].date)
  }

  // The date string to highlight in charts (only shown if it falls within the current trend window)
  const selDateForCharts = selectedDay?.date

  return (
    <div className="p-4 md:p-6 space-y-6 md:space-y-8">
      <h1 className="text-2xl font-bold text-white">Health</h1>

      <DailySnapshot
        day={selectedDay}
        snapshotWeight={snapshotWeight}
        avg30={summary?.avg_30d}
        intradayHr={intradayData?.hr_values}
        bodyBattery={intradayData?.body_battery}
        bbHires={intradayData?.body_battery_hires}
        sleepStages={intradayData?.sleep_stages}
        activities={dayActivities}
        latestVo2max={latestVo2max}
        birthYear={profile?.birth_year}
        biologicalSex={profile?.biological_sex}
        onOlder={goOlder}
        onNewer={goNewer}
        hasOlder={selectedIdx >= 0 && selectedIdx < allDaysSorted.length - 1}
        hasNewer={selectedIdx > 0}
      />

      <div className="border-t border-gray-800" />

      <div className="space-y-4">
        <div className="flex items-center justify-between flex-wrap gap-2">
          <div>
            <h2 className="text-base font-semibold text-gray-300">Trends</h2>
            <p className="text-xs text-gray-600">Click any point to load that day above</p>
          </div>
          <div className="flex flex-wrap gap-1.5">
            {RANGES.map(({ label, days }, i) => {
              const disabled = i > maxEnabledRangeIdx
              return (
                <button key={label}
                  onClick={() => !disabled && setRangeDays(days)}
                  disabled={disabled}
                  title={disabled ? 'Not enough history for this range' : undefined}
                  className={`text-xs px-3 py-1.5 rounded-full border transition-colors ${
                    disabled
                      ? 'border-gray-800 text-gray-700 opacity-40 cursor-not-allowed'
                      : rangeDays === days
                        ? 'bg-blue-600 border-blue-600 text-white'
                        : 'border-gray-700 text-gray-400 hover:text-white'
                  }`}>
                  {label}
                </button>
              )
            })}
          </div>
        </div>

        {isLoading ? (
          <div className="text-gray-500 text-sm">Loading…</div>
        ) : metrics.length > 0 ? (
          <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">

            <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
              <h3 className="text-sm font-medium text-gray-300 mb-3">Resting Heart Rate</h3>
              <MetricChart data={metrics} dataKey="resting_hr" color="#f43f5e"
                formatter={v => Math.round(v)}
                domain={[0, 200]}
                selectedDate={selDateForCharts} onDayClick={handleDayClick} />
            </div>

            <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
              <div className="flex items-center justify-between mb-3">
                <h3 className="text-sm font-medium text-gray-300">HRV (overnight avg)</h3>
                <div className="flex items-center gap-3 text-xs text-gray-500">
                  <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-full" style={{ background: '#22c55e' }} /> Balanced</span>
                  <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-full" style={{ background: '#f97316' }} /> Unbalanced</span>
                  <span className="flex items-center gap-1"><span className="w-3 h-2 rounded-sm" style={{ background: '#9ca3af', opacity: 0.5 }} /> Baseline</span>
                </div>
              </div>
              <MetricChart data={metrics} dataKey="hrv_weekly_avg" color="#8b5cf6"
                formatter={v => `${Math.round(v)} ms`}
                selectedDate={selDateForCharts} onDayClick={handleDayClick}
                statusDotKey="hrv_status"
                bandLowKey="hrv_baseline_low" bandHighKey="hrv_baseline_upper" bandColor="#9ca3af"
              />
            </div>

            <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
              <h3 className="text-sm font-medium text-gray-300 mb-3">Sleep</h3>
              <SleepChart data={metrics}
                selectedDate={selDateForCharts} onDayClick={handleDayClick} />
              <div className="flex gap-4 mt-2">
                {[['Deep','#6366f1'],['REM','#7c3aed'],['Light','#a78bfa'],['Awake','#eab308']].map(([l,c]) => (
                  <div key={l} className="flex items-center gap-1.5">
                    <div className="w-2.5 h-2.5 rounded-sm" style={{ backgroundColor: c }} />
                    <span className="text-xs text-gray-400">{l}</span>
                  </div>
                ))}
              </div>
            </div>

            {metrics.some(d => d.sleep_score != null) && (
              <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
                <h3 className="text-sm font-medium text-gray-300 mb-3">Sleep Score</h3>
                <MetricChart data={metrics} dataKey="sleep_score" color="#818cf8"
                  formatter={v => Math.round(v)}
                  domain={[0, 100]}
                  connectNulls showDots
                  selectedDate={selDateForCharts} onDayClick={handleDayClick}
                  referenceLines={[
                    { y: 80, stroke: '#22c55e', strokeDasharray: '3 3', label: { value: 'Good', position: 'insideTopRight', fill: '#22c55e', fontSize: 9 } },
                  ]}
                />
              </div>
            )}

            <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
              <WeightChart
                data={metrics}
                goalKg={profile?.goal_weight_kg}
                selectedDate={selDateForCharts} onDayClick={handleDayClick} />
            </div>

            <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
              <h3 className="text-sm font-medium text-gray-300 mb-3">Daily Steps</h3>
              <ResponsiveContainer width="100%" height={140}>
                <BarChart
                  data={metrics}
                  margin={{ top: 4, right: 4, bottom: 4, left: 0 }}
                  barSize={6}
                  style={{ cursor: 'pointer' }}
                  onClick={evt => {
                    const p = evt?.activePayload?.[0]?.payload
                    if (p?.date) handleDayClick(p.date)
                  }}
                >
                  <CartesianGrid strokeDasharray="3 3" stroke="#1f2937" vertical={false} />
                  <XAxis dataKey="date" tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false}
                    tickFormatter={d => format(new Date(d), 'MMM d')} interval="preserveStartEnd" />
                  <YAxis tick={{ fontSize: 10, fill: '#6b7280' }} axisLine={false} tickLine={false} width={36}
                    tickFormatter={v => v >= 1000 ? `${(v/1000).toFixed(0)}k` : v} />
                  <Tooltip contentStyle={tooltipStyle} labelFormatter={d => format(new Date(d), 'MMM d, yyyy')} />
                  {selDateForCharts && (
                    <ReferenceLine x={selDateForCharts} stroke="#60a5fa" strokeWidth={1.5} strokeDasharray="4 2" />
                  )}
                  <Bar dataKey="steps" name="Steps" fill="#fbbf24" radius={[2, 2, 0, 0]} isAnimationActive={false} />
                </BarChart>
              </ResponsiveContainer>
            </div>

            <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
              <h3 className="text-sm font-medium text-gray-300 mb-3">Stress Level</h3>
              <MetricChart data={metrics} dataKey="avg_stress" color="#a78bfa"
                formatter={v => Math.round(v)}
                domain={[0, 100]}
                selectedDate={selDateForCharts} onDayClick={handleDayClick} />
            </div>

            <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
              <h3 className="text-sm font-medium text-gray-300 mb-3">Heart Rate</h3>
              <MetricChart data={metrics} dataKey="avg_hr_day" color="#f97316"
                formatter={v => Math.round(v)}
                domain={[0, 200]}
                selectedDate={selDateForCharts} onDayClick={handleDayClick} />
            </div>

            {metrics.some(d => d.body_battery?.end_level != null) && (
              <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
                <h3 className="text-sm font-medium text-gray-300 mb-3">Body Battery (end of day)</h3>
                <MetricChart
                  data={metrics.map(d => ({ ...d, body_battery_level: d.body_battery?.end_level ?? null }))}
                  dataKey="body_battery_level" color="#3b82f6"
                  formatter={v => `${Math.round(v)}`}
                  selectedDate={selDateForCharts} onDayClick={handleDayClick} />
              </div>
            )}

            {metrics.some(d => d.vo2max) && (
              <div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
                <h3 className="text-sm font-medium text-gray-300 mb-3">VO2 Max</h3>
                <MetricChart data={metrics} dataKey="vo2max" color="#3b82f6"
                  formatter={v => v.toFixed(1)}
                  domain={[30, 70]}
                  connectNulls showDots
                  selectedDate={selDateForCharts} onDayClick={handleDayClick} />
              </div>
            )}

          </div>
        ) : (
          <div className="text-center py-12 text-gray-600">
            <p className="text-lg">No trend data for this period</p>
            <p className="text-sm mt-1">Try a longer date range</p>
          </div>
        )}
      </div>
    </div>
  )
}
