// Trends — rolling 14 days vs standards
const { useState, useEffect, useContext, useMemo, useRef } = React;

function TrendsPage() {
  const { entries, goals } = useContext(AppCtx);

  // last 14 days ending today
  const days = useMemo(() => {
    const today = todayISO();
    const out = [];
    for (let i = 13; i >= 0; i--) out.push(isoOffset(today, -i));
    return out;
  }, []);

  const series = useMemo(() => {
    return days.map(d => ({ date: d, totals: totalsForDay(entries, d) }));
  }, [entries, days]);

  // Stats across the 14 day window
  const stats = useMemo(() => {
    const keys = ['calories','protein','carbs','water','fat','fiber','sodium','caffeine'];
    const out = {};
    keys.forEach(k => {
      const arr = series.map(s => s.totals[k] || 0);
      const sum = arr.reduce((a,b) => a+b, 0);
      const avg = sum / arr.length;
      const max = Math.max(...arr);
      const min = Math.min(...arr);
      const daysOnGoal = arr.filter(v => goals[k] > 0 && v >= goals[k] * 0.85 && v <= goals[k] * 1.15).length;
      out[k] = { avg, max, min, daysOnGoal, sum };
    });
    return out;
  }, [series, goals]);

  return (
    <div>
      <div className="row-between mb-24" style={{ flexWrap: 'wrap', gap: 12 }}>
        <div>
          <div className="eyebrow">Trends · Last 14 Days</div>
          <h1 className="display mt-8">How you've fueled</h1>
          <p className="muted" style={{ maxWidth: 600 }}>
            Rolling daily totals plotted against your performance targets, with athlete-specific
            recommendations for mountain bike training.
          </p>
        </div>
        <div className="chip chip-accent">
          {days[0].slice(5).replace('-', '/')} → {days[days.length - 1].slice(5).replace('-', '/')}
        </div>
      </div>

      {/* Main charts */}
      <div className="grid grid-2 grid-cols-mobile-1 mb-24">
        <TrendChart title="Calories" unit="kcal" data={series.map(s => ({ d: s.date, v: s.totals.calories }))} goal={goals.calories} color="var(--accent)" stats={stats.calories} digits={0} />
        <TrendChart title="Protein" unit="g" data={series.map(s => ({ d: s.date, v: s.totals.protein }))} goal={goals.protein} color="var(--protein)" stats={stats.protein} digits={0} />
        <TrendChart title="Carbs" unit="g" data={series.map(s => ({ d: s.date, v: s.totals.carbs }))} goal={goals.carbs} color="var(--carbs)" stats={stats.carbs} digits={0} />
        <TrendChart title="Water" unit="oz" data={series.map(s => ({ d: s.date, v: s.totals.water }))} goal={goals.water} color="var(--water)" stats={stats.water} digits={0} />
      </div>

      {/* Bonus: small panels for fat, fiber, sodium, caffeine */}
      <div className="grid grid-4 mb-24">
        <MiniMetric title="Fat" stats={stats.fat} goal={goals.fat} unit="g" digits={1} />
        <MiniMetric title="Fiber" stats={stats.fiber} goal={goals.fiber} unit="g" digits={1} />
        <MiniMetric title="Sodium" stats={stats.sodium} goal={goals.sodium} unit="mg" digits={0} />
        <MiniMetric title="Caffeine" stats={stats.caffeine} goal={goals.caffeine} unit="mg" digits={0} />
      </div>

      {/* Performance Nutrition Suggestions */}
      <PerformanceSuggestions stats={stats} goals={goals} />
    </div>
  );
}

function TrendChart({ title, unit, data, goal, color, stats, digits = 0 }) {
  const canvasRef = useRef(null);
  const chartRef = useRef(null);

  useEffect(() => {
    if (!canvasRef.current || !window.Chart) return;
    const ctx = canvasRef.current.getContext('2d');
    if (chartRef.current) chartRef.current.destroy();

    const labels = data.map(d => d.d.slice(5));
    const values = data.map(d => d.v);

    // soft fill gradient
    const grad = ctx.createLinearGradient(0, 0, 0, 200);
    grad.addColorStop(0, hexAlpha(getCSSvar(color), 0.28));
    grad.addColorStop(1, hexAlpha(getCSSvar(color), 0));

    chartRef.current = new Chart(ctx, {
      type: 'line',
      data: {
        labels,
        datasets: [{
          label: title,
          data: values,
          borderColor: getCSSvar(color),
          backgroundColor: grad,
          tension: 0.35,
          fill: true,
          pointRadius: 3,
          pointHoverRadius: 5,
          pointBackgroundColor: getCSSvar(color),
          pointBorderColor: getCSSvar('--bg-card'),
          pointBorderWidth: 2,
          borderWidth: 2.5
        }]
      },
      options: {
        plugins: {
          legend: { display: false },
          tooltip: {
            backgroundColor: getCSSvar('--bg-elev'),
            borderColor: getCSSvar('--line'),
            borderWidth: 1,
            titleColor: getCSSvar('--text'),
            bodyColor: getCSSvar('--text-soft'),
            padding: 10,
            callbacks: {
              label: (ctx) => `${Math.round(ctx.raw)} ${unit}`
            }
          },
          annotation: false
        },
        responsive: true,
        maintainAspectRatio: false,
        scales: {
          y: {
            beginAtZero: true,
            grid: { color: getCSSvar('--line-soft'), drawBorder: false },
            ticks: { color: getCSSvar('--text-dim'), font: { family: 'JetBrains Mono', size: 11 } }
          },
          x: {
            grid: { display: false },
            ticks: { color: getCSSvar('--text-dim'), maxRotation: 0, font: { size: 10 } }
          }
        }
      },
      plugins: [{
        id: 'goalLine',
        afterDatasetsDraw(chart) {
          if (!goal) return;
          const yScale = chart.scales.y;
          const y = yScale.getPixelForValue(goal);
          if (y < chart.chartArea.top || y > chart.chartArea.bottom) return;
          const c = chart.ctx;
          c.save();
          c.strokeStyle = getCSSvar('--text-dim');
          c.setLineDash([4, 4]);
          c.lineWidth = 1;
          c.beginPath();
          c.moveTo(chart.chartArea.left, y);
          c.lineTo(chart.chartArea.right, y);
          c.stroke();
          c.setLineDash([]);
          c.font = '600 10px Inter';
          c.fillStyle = getCSSvar('--text-dim');
          c.textAlign = 'right';
          c.fillText(`Goal · ${goal}`, chart.chartArea.right - 4, y - 4);
          c.restore();
        }
      }]
    });
    return () => { if (chartRef.current) chartRef.current.destroy(); };
  }, [data, goal, color, title, unit]);

  return (
    <div className="card">
      <div className="row-between mb-12" style={{ alignItems: 'flex-start' }}>
        <div>
          <h3>{title}</h3>
          <div className="muted" style={{ fontSize: 12 }}>14-day average</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="num" style={{ fontSize: 26, color, lineHeight: 1 }}>{fmtNum(stats.avg, digits)}</div>
          <div className="muted" style={{ fontSize: 11 }}>{unit} / day</div>
        </div>
      </div>
      <div style={{ height: 170 }}>
        <canvas ref={canvasRef} />
      </div>
      <div className="row mt-12" style={{ gap: 14, fontSize: 11, color: 'var(--text-soft)', flexWrap: 'wrap' }}>
        <span>High <strong className="num" style={{ color: 'var(--text)' }}>{fmtNum(stats.max, digits)}</strong></span>
        <span>Low <strong className="num" style={{ color: 'var(--text)' }}>{fmtNum(stats.min, digits)}</strong></span>
        <span>On target <strong className="num" style={{ color: 'var(--good)' }}>{stats.daysOnGoal}/14</strong></span>
      </div>
    </div>
  );
}

function MiniMetric({ title, stats, goal, unit, digits = 0 }) {
  const dist = goal > 0 ? Math.round((stats.avg / goal) * 100) : 0;
  return (
    <div className="card-tight card">
      <div className="stat-label">{title}</div>
      <div className="row-between mt-8" style={{ alignItems: 'flex-end' }}>
        <div className="num" style={{ fontSize: 22 }}>{fmtNum(stats.avg, digits)}<span className="dim" style={{ fontSize: 12, marginLeft: 2 }}>{unit}</span></div>
        <div className="num" style={{ fontSize: 11, color: 'var(--text-dim)' }}>{dist}% of goal</div>
      </div>
      <div className="mt-8">
        <Progress value={stats.avg} max={goal} />
      </div>
    </div>
  );
}

/* ---------- Performance Nutrition Suggestions ---------- */
function PerformanceSuggestions({ stats, goals }) {
  const suggestions = useMemo(() => buildSuggestions(stats, goals), [stats, goals]);

  return (
    <div className="card">
      <div className="row-between mb-16" style={{ flexWrap: 'wrap', gap: 8 }}>
        <div>
          <h3>Performance Nutrition Suggestions</h3>
          <div className="muted" style={{ fontSize: 13 }}>For mountain biking · 150 lb athlete</div>
        </div>
        <span className="chip chip-accent"><Icon name="sparkle" size={12} /> Rule-based</span>
      </div>

      <div className="grid grid-2 grid-cols-mobile-1">
        {suggestions.map((s, i) => (
          <div key={i} style={{
            border: '1px solid var(--line)', borderRadius: 14, padding: 16,
            background: s.urgent ? 'var(--accent-soft)' : 'var(--bg-elev)'
          }}>
            <div className="row" style={{ gap: 8, marginBottom: 6 }}>
              <span className={`chip ${s.urgent ? 'badge-bad' : s.good ? 'badge-good' : 'badge-warn'}`}>{s.tag}</span>
            </div>
            <div style={{ fontWeight: 500, fontSize: 15, marginBottom: 4 }}>{s.title}</div>
            <p style={{ margin: 0, color: 'var(--text-soft)', fontSize: 13 }}>{s.body}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

function buildSuggestions(stats, goals) {
  const out = [];
  // Protein
  const proteinAvg = stats.protein.avg;
  if (proteinAvg < goals.protein * 0.8) {
    out.push({
      tag: 'Protein low', urgent: true,
      title: `Bump protein toward ${goals.protein} g/day`,
      body: `Your 14-day average is ${Math.round(proteinAvg)} g — ~${Math.round(((goals.protein - proteinAvg)/goals.protein)*100)}% below target. Add 25–35 g post-ride (whey or Greek yogurt) and lean meat at lunch to support muscle repair.`
    });
  } else if (proteinAvg >= goals.protein * 0.95) {
    out.push({
      tag: 'Protein dialed in', good: true,
      title: 'Protein intake on point',
      body: `Averaging ${Math.round(proteinAvg)} g/day matches your performance target. Keep spreading it across 3–4 feedings/day for steady muscle protein synthesis.`
    });
  } else {
    out.push({
      tag: 'Protein OK', good: false,
      title: 'Close on protein, push to ceiling',
      body: `${Math.round(proteinAvg)} g/day average — within striking distance of the ${goals.protein} g target. Adding one more 20 g serving (eggs, milk, jerky) seals it.`
    });
  }

  // Carbs (cyclist's primary fuel)
  const carbsAvg = stats.carbs.avg;
  if (carbsAvg < goals.carbs * 0.8) {
    out.push({
      tag: 'Carbs low', urgent: true,
      title: 'Fuel the engine — load carbs around rides',
      body: `Mountain biking burns 600–900 kcal/hr. At ${Math.round(carbsAvg)} g/day you're under-fueled. Front-load 80–120 g carbs in the 2 hr pre-ride and 60–90 g/hr during anything over 90 min.`
    });
  } else if (carbsAvg >= goals.carbs * 0.95 && carbsAvg <= goals.carbs * 1.15) {
    out.push({
      tag: 'Carbs on target', good: true,
      title: 'Carb intake matches training demand',
      body: `${Math.round(carbsAvg)} g/day average is in the 5–7 g/kg sweet spot for an active endurance athlete. Focus on timing — biggest carbs 1–3 hr around training.`
    });
  } else if (carbsAvg > goals.carbs * 1.15) {
    out.push({
      tag: 'Carbs high', good: false,
      title: 'High carb floor — check ride volume',
      body: `${Math.round(carbsAvg)} g/day is well above your ${goals.carbs} g target. Fine if you're in a heavy training block; otherwise trim refined sugars and prioritize whole-food carbs.`
    });
  }

  // Hydration
  const waterAvg = stats.water.avg;
  if (waterAvg < goals.water * 0.7) {
    out.push({
      tag: 'Hydration low', urgent: true,
      title: 'Drink more, every day',
      body: `Averaging ${Math.round(waterAvg)} oz/day vs ${goals.water} oz target. Aim for half your body weight in oz baseline + 20–24 oz per hour of riding. Add electrolytes for rides >60 min.`
    });
  } else {
    out.push({
      tag: 'Hydration steady', good: true,
      title: 'Hydration trending well',
      body: `${Math.round(waterAvg)} oz/day average covers baseline needs. On ride days, top up 16–24 oz per hour and add sodium (300–700 mg/L) on long efforts.`
    });
  }

  // Fiber
  const fiberAvg = stats.fiber.avg;
  if (fiberAvg < goals.fiber * 0.7) {
    out.push({
      tag: 'Fiber low', urgent: false,
      title: 'Add color and fiber',
      body: `${Math.round(fiberAvg)} g/day vs ${goals.fiber} g goal. Berries, oats, beans, and an extra serving of veg at dinner gets you there without bloating mid-ride.`
    });
  }

  // Sodium (matters for endurance athletes)
  const sodiumAvg = stats.sodium.avg;
  if (sodiumAvg < 2000) {
    out.push({
      tag: 'Sodium low for endurance', good: false,
      title: 'Endurance athletes need more sodium',
      body: `${Math.round(sodiumAvg)} mg/day average is on the low side for a sweaty MTB rider. Don't fear salt — pickles, broth, and salted nuts help replenish what you sweat out.`
    });
  } else if (sodiumAvg > 4000) {
    out.push({
      tag: 'Sodium high', good: false,
      title: 'Sodium ceiling — moderate processed foods',
      body: `${Math.round(sodiumAvg)} mg/day is elevated. Save the salt budget for around training sessions; cut back on processed meats and packaged snacks on rest days.`
    });
  }

  // Caffeine
  const caffeineAvg = stats.caffeine.avg;
  if (caffeineAvg > 350) {
    out.push({
      tag: 'Caffeine high', urgent: false,
      title: 'Watch the caffeine ceiling',
      body: `Averaging ${Math.round(caffeineAvg)} mg/day. Strategic 3–5 mg/kg pre-ride is performance-enhancing, but daily 400+ mg can blunt sleep and recovery. Cap caffeine 8 hr before bed.`
    });
  }

  // Calories vs goal
  const calAvg = stats.calories.avg;
  if (calAvg < goals.calories * 0.8) {
    out.push({
      tag: 'Energy deficit', urgent: true,
      title: 'You may be under-fueled',
      body: `${Math.round(calAvg)} kcal/day average is below your ${goals.calories} target. Sustained under-fueling tanks training quality and immune function. Add an evening snack with carbs + protein.`
    });
  }

  return out.slice(0, 6);
}

function hexAlpha(color, alpha) {
  // accept "#rrggbb" or "rgb(...)" or named color via canvas
  try {
    const c = document.createElement('canvas').getContext('2d');
    c.fillStyle = color || '#000';
    const v = c.fillStyle; // "#rrggbb"
    const r = parseInt(v.slice(1,3),16), g = parseInt(v.slice(3,5),16), b = parseInt(v.slice(5,7),16);
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
  } catch (e) { return color; }
}
function getCSSvar(token) {
  if (!token) return '#000';
  if (token.startsWith('var(')) token = token.slice(4, -1);
  if (token.startsWith('--')) {
    return getComputedStyle(document.documentElement).getPropertyValue(token).trim() || '#888';
  }
  return token;
}

window.TrendsPage = TrendsPage;
