import React, { useState, useRef, useMemo, useCallback, useEffect } from "react";
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from "recharts";
import {
  Mic,
  MicOff,
  Plus,
  Trash2,
  Pencil,
  Check,
  X,
  Flame,
  UtensilsCrossed,
  CalendarDays,
  CalendarRange,
  BarChart3,
  AlertCircle,
  Coffee,
  Sandwich,
  Soup,
  Cookie,
  ChevronLeft,
  ChevronRight,
} from "lucide-react";

/* ---------------------------------------------------------
   DESIGN TOKENS — "Electric Slate"
--------------------------------------------------------- */

const BG = "#0F172A";
const SURFACE = "#1E293B";
const BORDER = "#334155";
const MUTED = "#94A3B8";
const TEXT = "#F1F5F9";

const COLORS = {
  cal: "#8B5CF6",
  protein: "#FF5A5F",
  carbs: "#F59E0B",
  fat: "#06B6D4",
};

/* Daily target split: 35% protein / 40% carbs / 25% fat of a
   2,000 kcal day. Protein & carbs at 4 kcal/g, fat at 9 kcal/g. */
const GOALS = {
  calories: 2000,
  protein: Math.round((2000 * 0.35) / 4), // 175g
  carbs: Math.round((2000 * 0.4) / 4), // 200g
  fat: Math.round((2000 * 0.25) / 9), // 56g
};

const MEAL_TYPE_ORDER = ["Breakfast", "Lunch", "Dinner", "Snack"];
const MEAL_TYPE_META = {
  Breakfast: { icon: Coffee, blurb: "Start the day" },
  Lunch: { icon: Sandwich, blurb: "Midday fuel" },
  Dinner: { icon: Soup, blurb: "Evening meal" },
  Snack: { icon: Cookie, blurb: "Something small" },
};

/* ---------------------------------------------------------
   DATE HELPERS
--------------------------------------------------------- */

function toISODate(d) {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

function daysAgoISO(n) {
  const d = new Date();
  d.setHours(0, 0, 0, 0);
  d.setDate(d.getDate() - n);
  return toISODate(d);
}

function isoToTimestamp(iso) {
  return new Date(`${iso}T00:00:00`).getTime();
}

function friendlyDateLabel(iso) {
  const today = daysAgoISO(0);
  const yesterday = daysAgoISO(1);
  if (iso === today) return "Today";
  if (iso === yesterday) return "Yesterday";
  const d = new Date(`${iso}T00:00:00`);
  return d.toLocaleDateString([], { weekday: "short", month: "short", day: "numeric" });
}

/* ---------------------------------------------------------
   MOCK MACRO-PARSING ENGINE (for freeform text/voice entries)
--------------------------------------------------------- */

const FOOD_DB = [
  ["scrambled egg", { cal: 90, protein: 6, carbs: 1, fat: 7 }],
  ["fried egg", { cal: 90, protein: 6, carbs: 0.5, fat: 7 }],
  ["boiled egg", { cal: 78, protein: 6, carbs: 0.5, fat: 5 }],
  ["egg", { cal: 70, protein: 6, carbs: 0.5, fat: 5 }],
  ["sourdough", { cal: 120, protein: 4, carbs: 23, fat: 1 }],
  ["toast", { cal: 75, protein: 3, carbs: 13, fat: 1 }],
  ["bread", { cal: 100, protein: 3, carbs: 18, fat: 1 }],
  ["chicken breast", { cal: 165, protein: 31, carbs: 0, fat: 3.6 }],
  ["chicken salad", { cal: 220, protein: 22, carbs: 8, fat: 11 }],
  ["chicken", { cal: 165, protein: 31, carbs: 0, fat: 3.6 }],
  ["greek yogurt", { cal: 130, protein: 17, carbs: 6, fat: 4 }],
  ["yogurt", { cal: 100, protein: 10, carbs: 8, fat: 3 }],
  ["salad", { cal: 120, protein: 3, carbs: 10, fat: 8 }],
  ["white rice", { cal: 205, protein: 4.2, carbs: 45, fat: 0.4 }],
  ["brown rice", { cal: 216, protein: 5, carbs: 45, fat: 1.8 }],
  ["rice", { cal: 205, protein: 4, carbs: 44, fat: 0.4 }],
  ["avocado", { cal: 240, protein: 3, carbs: 12, fat: 22 }],
  ["banana", { cal: 105, protein: 1.3, carbs: 27, fat: 0.4 }],
  ["oatmeal", { cal: 150, protein: 5, carbs: 27, fat: 3 }],
  ["salmon", { cal: 206, protein: 22, carbs: 0, fat: 13 }],
  ["steak", { cal: 271, protein: 26, carbs: 0, fat: 19 }],
  ["ground beef", { cal: 250, protein: 26, carbs: 0, fat: 17 }],
  ["beef", { cal: 250, protein: 26, carbs: 0, fat: 17 }],
  ["pasta", { cal: 220, protein: 8, carbs: 43, fat: 1.3 }],
  ["peanut butter", { cal: 190, protein: 8, carbs: 6, fat: 16 }],
  ["cheese", { cal: 110, protein: 7, carbs: 1, fat: 9 }],
  ["apple", { cal: 95, protein: 0.5, carbs: 25, fat: 0.3 }],
  ["almonds", { cal: 170, protein: 6, carbs: 6, fat: 15 }],
  ["protein shake", { cal: 150, protein: 25, carbs: 5, fat: 2 }],
  ["milk", { cal: 120, protein: 8, carbs: 12, fat: 5 }],
  ["black coffee", { cal: 5, protein: 0.3, carbs: 1, fat: 0 }],
  ["coffee", { cal: 15, protein: 0.5, carbs: 2, fat: 0.5 }],
  ["olive oil", { cal: 120, protein: 0, carbs: 0, fat: 14 }],
  ["quinoa", { cal: 220, protein: 8, carbs: 39, fat: 3.5 }],
  ["sweet potato", { cal: 112, protein: 2, carbs: 26, fat: 0.1 }],
  ["broccoli", { cal: 55, protein: 3.7, carbs: 11, fat: 0.6 }],
  ["tuna", { cal: 132, protein: 29, carbs: 0, fat: 1 }],
  ["turkey", { cal: 135, protein: 25, carbs: 0, fat: 3 }],
  ["granola", { cal: 200, protein: 5, carbs: 30, fat: 8 }],
  ["protein bar", { cal: 200, protein: 20, carbs: 20, fat: 7 }],
].sort((a, b) => b[0].length - a[0].length);

const FILLER_WORDS = [
  "slices of", "slice of", "cups of", "cup of", "pieces of", "piece of",
  "servings of", "serving of", "bowl of", "glass of", "handful of",
  "slices", "slice", "cups", "cup", "pieces", "piece", "servings",
  "serving", "of", "a", "an", "some",
];

function stripFillers(str) {
  let out = str.trim();
  FILLER_WORDS.forEach((w) => {
    out = out.replace(new RegExp(`\\b${w}\\b`, "gi"), " ");
  });
  return out.replace(/\s+/g, " ").trim();
}

function matchFood(segmentLower) {
  for (const [key, macros] of FOOD_DB) {
    if (segmentLower.includes(key)) return macros;
  }
  return null;
}

// Meal type is now captured separately via the picker, so this only
// ever needs to turn free text into estimated macros.
function parseMacros(raw) {
  const text = raw.trim();
  if (!text) return null;

  const segments = text.split(/,| and |\+|;/i).map((s) => s.trim()).filter(Boolean);
  const items = segments.length ? segments : [text];

  let totals = { cal: 0, protein: 0, carbs: 0, fat: 0 };

  items.forEach((segment) => {
    const qtyMatch = segment.match(/^(\d+(?:\.\d+)?)\s*/);
    const qty = qtyMatch ? parseFloat(qtyMatch[1]) : 1;
    const rest = segment.replace(/^(\d+(?:\.\d+)?)\s*/, "");
    const cleaned = stripFillers(rest).toLowerCase();
    const found = matchFood(cleaned);
    const macros = found || { cal: 180, protein: 9, carbs: 20, fat: 7 };
    totals.cal += macros.cal * qty;
    totals.protein += macros.protein * qty;
    totals.carbs += macros.carbs * qty;
    totals.fat += macros.fat * qty;
  });

  return {
    calories: Math.round(totals.cal),
    protein: Math.round(totals.protein * 10) / 10,
    carbs: Math.round(totals.carbs * 10) / 10,
    fat: Math.round(totals.fat * 10) / 10,
  };
}

/* ---------------------------------------------------------
   REALISTIC MOCK DATA — spans 10 days so "Weekly Avg" (7d)
   is fully populated and "Monthly Avg" (30d window) has a
   real sample, and Meal History has days to light up.
--------------------------------------------------------- */

const MEAL_TEMPLATES = {
  B1: { mealType: "Breakfast", raw: "3 scrambled eggs, 2 slices sourdough, avocado", calories: 520, protein: 28, carbs: 38, fat: 26, time: "08:12 AM" },
  B2: { mealType: "Breakfast", raw: "Greek yogurt with granola and banana", calories: 380, protein: 22, carbs: 52, fat: 9, time: "07:48 AM" },
  L1: { mealType: "Lunch", raw: "Grilled chicken salad with olive oil dressing", calories: 460, protein: 38, carbs: 18, fat: 24, time: "12:34 PM" },
  L2: { mealType: "Lunch", raw: "Turkey sandwich with cheese and apple", calories: 540, protein: 32, carbs: 55, fat: 18, time: "01:05 PM" },
  D1: { mealType: "Dinner", raw: "Salmon, quinoa and broccoli", calories: 610, protein: 42, carbs: 46, fat: 24, time: "07:20 PM" },
  D2: { mealType: "Dinner", raw: "Steak with sweet potato", calories: 690, protein: 44, carbs: 42, fat: 34, time: "07:55 PM" },
  S1: { mealType: "Snack", raw: "Protein shake and almonds", calories: 340, protein: 28, carbs: 14, fat: 18, time: "03:40 PM" },
  S2: { mealType: "Snack", raw: "Apple and peanut butter", calories: 285, protein: 8, carbs: 26, fat: 17, time: "09:15 PM" },
};

const DAY_PATTERNS = [
  ["B1", "L1"],                 // today — partial day, still in progress
  ["B2", "L2", "D1", "S1"],     // yesterday
  ["B1", "L2", "D2", "S2"],
  ["B2", "L1", "D1"],
  ["B1", "L2", "D2", "S1"],
  ["B2", "L1", "D2", "S2"],
  ["B1", "L1", "D1", "S2"],
  ["B2", "L2", "D2"],
  ["B1", "L1", "D1", "S1"],
  ["B2", "L2", "D1", "S2"],
];

function buildMockEntries() {
  const entries = [];
  DAY_PATTERNS.forEach((pattern, dayIndex) => {
    const dateISO = daysAgoISO(dayIndex);
    pattern.forEach((key, mealIndex) => {
      const t = MEAL_TEMPLATES[key];
      entries.push({ id: `mock-${dayIndex}-${mealIndex}`, dateISO, ...t });
    });
  });
  return entries;
}

/* ---------------------------------------------------------
   AGGREGATION — daily totals, or "logged-days" averages for
   weekly / monthly windows.
--------------------------------------------------------- */

function aggregate(entries, windowDays, averaged) {
  const todayISO = daysAgoISO(0);
  const cutoffTs = isoToTimestamp(daysAgoISO(windowDays - 1));

  const inRange = entries.filter((e) => isoToTimestamp(e.dateISO) >= cutoffTs);
  const relevant = averaged ? inRange : entries.filter((e) => e.dateISO === todayISO);

  const byDate = new Map();
  relevant.forEach((e) => {
    const acc = byDate.get(e.dateISO) || { calories: 0, protein: 0, carbs: 0, fat: 0 };
    acc.calories += e.calories;
    acc.protein += e.protein;
    acc.carbs += e.carbs;
    acc.fat += e.fat;
    byDate.set(e.dateISO, acc);
  });

  const loggedDays = Math.max(byDate.size, 1);
  const sum = { calories: 0, protein: 0, carbs: 0, fat: 0 };
  byDate.forEach((v) => {
    sum.calories += v.calories;
    sum.protein += v.protein;
    sum.carbs += v.carbs;
    sum.fat += v.fat;
  });

  const divisor = averaged ? loggedDays : 1;
  return {
    calories: sum.calories / divisor,
    protein: sum.protein / divisor,
    carbs: sum.carbs / divisor,
    fat: sum.fat / divisor,
    loggedDays: byDate.size,
  };
}

const TABS = [
  { key: "daily", label: "Daily", icon: CalendarDays },
  { key: "weekly", label: "Weekly Avg", icon: CalendarRange },
  { key: "monthly", label: "Monthly Avg", icon: BarChart3 },
];

/* ---------------------------------------------------------
   CALORIE DIAL — signature element
--------------------------------------------------------- */

function CalorieDial({ consumed, goal, tabLabel }) {
  const size = 220;
  const stroke = 14;
  const r = (size - stroke) / 2 - 10;
  const cx = size / 2;
  const cy = size / 2;
  const circumference = 2 * Math.PI * r;
  const pct = Math.min(consumed / goal, 1);
  const dash = circumference * pct;
  const over = consumed > goal;
  const remaining = Math.abs(goal - consumed);
  const goalPct = Math.round((consumed / goal) * 100);

  const ticks = Array.from({ length: 40 }, (_, i) => {
    const angle = (i / 40) * 360 - 90;
    const rad = (angle * Math.PI) / 180;
    const major = i % 5 === 0;
    const outerR = r + stroke / 2 + 6;
    const innerR = outerR - (major ? 9 : 4);
    return {
      x1: cx + outerR * Math.cos(rad),
      y1: cy + outerR * Math.sin(rad),
      x2: cx + innerR * Math.cos(rad),
      y2: cy + innerR * Math.sin(rad),
      major,
    };
  });

  return (
    <div className="relative flex items-center justify-center">
      <svg width={size} height={size}>
        {ticks.map((t, i) => (
          <line key={i} x1={t.x1} y1={t.y1} x2={t.x2} y2={t.y2} stroke={t.major ? "#475569" : "#293548"} strokeWidth={t.major ? 2 : 1.5} strokeLinecap="round" />
        ))}
        <circle cx={cx} cy={cy} r={r} fill="none" stroke={BORDER} strokeWidth={stroke} />
        <circle
          cx={cx}
          cy={cy}
          r={r}
          fill="none"
          stroke={over ? COLORS.protein : COLORS.cal}
          strokeWidth={stroke}
          strokeLinecap="round"
          strokeDasharray={`${dash} ${circumference - dash}`}
          transform={`rotate(-90 ${cx} ${cy})`}
          style={{ transition: "stroke-dasharray 0.5s ease" }}
        />
      </svg>
      <div className="absolute flex flex-col items-center">
        <Flame size={16} className="mb-1" style={{ color: over ? COLORS.protein : COLORS.cal }} />
        <span className="font-mono text-4xl font-bold tabular-nums leading-none" style={{ color: TEXT }}>
          {Math.round(consumed).toLocaleString()}
        </span>
        <span className="text-[11px] uppercase tracking-widest mt-1" style={{ color: MUTED }}>
          of {goal.toLocaleString()} kcal
        </span>
        <span className="text-[10px] uppercase tracking-widest mt-0.5" style={{ color: MUTED }}>
          {tabLabel}
        </span>
        <span
          className="mt-2 text-xs font-mono px-2 py-0.5 rounded-full border"
          style={{
            color: over ? COLORS.protein : COLORS.fat,
            borderColor: over ? "#5C2A2C" : "#164E5C",
            background: over ? "#291517" : "#0C2229",
          }}
        >
          {goalPct}% · {over ? `${Math.round(remaining)} over` : `${Math.round(remaining)} left`}
        </span>
      </div>
    </div>
  );
}

/* ---------------------------------------------------------
   MACRO BAR — absolute value + % of goal + % of intake
--------------------------------------------------------- */

function MacroBar({ label, value, goal, color, compositionPct }) {
  const goalPct = Math.min(Math.round((value / goal) * 100), 999);
  const barPct = Math.min((value / goal) * 100, 100);
  return (
    <div>
      <div className="flex items-baseline justify-between mb-1.5">
        <div className="flex items-center gap-2">
          <span className="h-2 w-2 rounded-full" style={{ background: color }} />
          <span className="text-xs font-medium uppercase tracking-wider" style={{ color: MUTED }}>{label}</span>
        </div>
        <div className="flex items-center gap-2">
          <span className="text-[11px] font-mono px-1.5 py-0.5 rounded" style={{ color, background: `${color}1A` }}>
            {compositionPct}% of intake
          </span>
          <span className="font-mono text-sm" style={{ color: TEXT }}>
            {Math.round(value)}
            <span style={{ color: MUTED }}>g/{goal}g</span>
          </span>
        </div>
      </div>
      <div className="h-2 w-full rounded-full overflow-hidden" style={{ background: "#0F172A" }}>
        <div className="h-full rounded-full transition-all duration-500" style={{ width: `${barPct}%`, background: color }} />
      </div>
      <div className="text-[10px] font-mono mt-1" style={{ color: MUTED }}>{goalPct}% of daily target</div>
    </div>
  );
}

/* ---------------------------------------------------------
   CUSTOM TOOLTIP for the donut chart — grams + kcal + %
--------------------------------------------------------- */

function DonutTooltip({ active, payload }) {
  if (!active || !payload || !payload.length) return null;
  const d = payload[0].payload;
  if (d.empty) return null;
  return (
    <div className="rounded-lg px-3 py-2 text-xs" style={{ background: SURFACE, border: `1px solid ${BORDER}`, color: TEXT }}>
      <div className="font-semibold mb-0.5" style={{ color: d.color }}>{d.name}</div>
      <div className="font-mono">{Math.round(d.value)} kcal</div>
      <div className="font-mono" style={{ color: MUTED }}>{d.grams}g · {d.pct}% of intake</div>
    </div>
  );
}

/* ---------------------------------------------------------
   TOAST
--------------------------------------------------------- */

function Toast({ message }) {
  if (!message) return null;
  return (
    <div className="fixed bottom-5 left-1/2 -translate-x-1/2 z-[60] max-w-[92%]">
      <div className="flex items-center gap-2 rounded-full px-4 py-2.5 text-xs shadow-xl" style={{ background: SURFACE, border: `1px solid ${BORDER}`, color: TEXT }}>
        <AlertCircle size={14} style={{ color: COLORS.protein }} />
        {message}
      </div>
    </div>
  );
}

/* ---------------------------------------------------------
   ENTRY CARD — shared between today's log and meal history
--------------------------------------------------------- */

function EntryCard({ entry, isEditing, editDraft, setEditDraft, onStartEdit, onCancelEdit, onSaveEdit, onDelete }) {
  return (
    <div className="rounded-2xl p-4" style={{ background: SURFACE, border: `1px solid ${BORDER}` }}>
      {isEditing ? (
        <div className="space-y-3">
          <div>
            <label className="text-[10px] uppercase tracking-wider" style={{ color: MUTED }}>Meal type</label>
            <div className="grid grid-cols-4 gap-1.5 mt-1">
              {MEAL_TYPE_ORDER.map((type) => (
                <button
                  key={type}
                  onClick={() => setEditDraft((d) => ({ ...d, mealType: type }))}
                  className="rounded-lg py-1.5 text-[11px] font-semibold"
                  style={
                    editDraft.mealType === type
                      ? { background: COLORS.cal, color: "#fff" }
                      : { background: BG, border: `1px solid ${BORDER}`, color: MUTED }
                  }
                >
                  {type}
                </button>
              ))}
            </div>
          </div>
          <div>
            <label className="text-[10px] uppercase tracking-wider" style={{ color: MUTED }}>Description</label>
            <input
              value={editDraft.raw}
              onChange={(e) => setEditDraft((d) => ({ ...d, raw: e.target.value }))}
              className="w-full mt-1 rounded-lg px-3 py-2 text-sm bg-transparent focus:outline-none"
              style={{ border: `1px solid ${BORDER}`, color: TEXT }}
            />
          </div>
          <div className="grid grid-cols-4 gap-2">
            {[
              { key: "calories", label: "Kcal", color: COLORS.cal },
              { key: "protein", label: "Protein", color: COLORS.protein },
              { key: "carbs", label: "Carbs", color: COLORS.carbs },
              { key: "fat", label: "Fat", color: COLORS.fat },
            ].map((f) => (
              <div key={f.key}>
                <label className="text-[10px] uppercase tracking-wider" style={{ color: f.color }}>{f.label}</label>
                <input
                  type="number"
                  value={editDraft[f.key]}
                  onChange={(e) => setEditDraft((d) => ({ ...d, [f.key]: e.target.value }))}
                  className="w-full mt-1 rounded-lg px-2 py-1.5 text-sm bg-transparent focus:outline-none font-mono"
                  style={{ border: `1px solid ${BORDER}`, color: TEXT }}
                />
              </div>
            ))}
          </div>
          <div className="flex justify-end gap-2 pt-1">
            <button onClick={onCancelEdit} className="flex items-center gap-1 rounded-full px-3 py-1.5 text-xs font-semibold" style={{ background: BG, border: `1px solid ${BORDER}`, color: MUTED }}>
              <X size={13} /> Cancel
            </button>
            <button onClick={onSaveEdit} className="flex items-center gap-1 rounded-full px-3 py-1.5 text-xs font-semibold" style={{ background: COLORS.cal, color: "#fff" }}>
              <Check size={13} /> Save
            </button>
          </div>
        </div>
      ) : (
        <>
          <div className="flex items-start justify-between gap-3">
            <div className="min-w-0">
              <div className="flex items-center gap-2">
                <span className="text-sm font-semibold">{entry.mealType}</span>
                <span className="text-[11px] font-mono" style={{ color: MUTED }}>{entry.time}</span>
              </div>
              <p className="text-xs mt-0.5 truncate" style={{ color: MUTED }}>{entry.raw}</p>
            </div>
            <div className="flex items-center gap-2 shrink-0">
              <div className="text-right">
                <div className="font-mono text-sm font-semibold" style={{ color: COLORS.cal }}>{entry.calories}</div>
                <div className="text-[10px]" style={{ color: MUTED }}>kcal</div>
              </div>
              <button onClick={onStartEdit} className="h-8 w-8 rounded-full flex items-center justify-center" style={{ color: MUTED }} aria-label={`Edit ${entry.mealType}`}>
                <Pencil size={14} />
              </button>
              <button onClick={onDelete} className="h-8 w-8 rounded-full flex items-center justify-center" style={{ color: MUTED }} aria-label={`Delete ${entry.mealType}`}>
                <Trash2 size={14} />
              </button>
            </div>
          </div>
          <div className="flex gap-3 mt-3 pt-3" style={{ borderTop: `1px solid ${BORDER}` }}>
            <span className="text-[11px] font-mono" style={{ color: COLORS.protein }}>P {entry.protein}g</span>
            <span className="text-[11px] font-mono" style={{ color: COLORS.carbs }}>C {entry.carbs}g</span>
            <span className="text-[11px] font-mono" style={{ color: COLORS.fat }}>F {entry.fat}g</span>
          </div>
        </>
      )}
    </div>
  );
}

/* ---------------------------------------------------------
   MAIN APP
--------------------------------------------------------- */

export default function NutritionTracker() {
  const [entries, setEntries] = useState(() => buildMockEntries());
  const [activeTab, setActiveTab] = useState("daily");

  const [editingId, setEditingId] = useState(null);
  const [editDraft, setEditDraft] = useState(null);
  const [toast, setToast] = useState(null);

  // Log Food modal
  const [logModalOpen, setLogModalOpen] = useState(false);
  const [logStep, setLogStep] = useState("select-type"); // 'select-type' | 'input'
  const [selectedMealType, setSelectedMealType] = useState(null);
  const [inputText, setInputText] = useState("");
  const [listening, setListening] = useState(false);

  // Meal History modal
  const [historyOpen, setHistoryOpen] = useState(false);
  const [calendarMonth, setCalendarMonth] = useState(() => {
    const d = new Date();
    return new Date(d.getFullYear(), d.getMonth(), 1);
  });
  const [selectedHistoryDate, setSelectedHistoryDate] = useState(() => daysAgoISO(0));

  const recognitionRef = useRef(null);
  const toastTimeoutRef = useRef(null);

  const speechSupported =
    typeof window !== "undefined" && !!(window.SpeechRecognition || window.webkitSpeechRecognition);

  const showToast = useCallback((message) => {
    if (toastTimeoutRef.current) clearTimeout(toastTimeoutRef.current);
    setToast(message);
    toastTimeoutRef.current = setTimeout(() => setToast(null), 3500);
  }, []);

  useEffect(() => () => toastTimeoutRef.current && clearTimeout(toastTimeoutRef.current), []);

  /* ----- aggregated totals per tab (dashboard) ----- */
  const activeStats = useMemo(() => {
    if (activeTab === "daily") return { ...aggregate(entries, 1, false), rangeLabel: "TODAY" };
    if (activeTab === "weekly") return { ...aggregate(entries, 7, true), rangeLabel: "WEEKLY AVG / DAY" };
    return { ...aggregate(entries, 30, true), rangeLabel: "MONTHLY AVG / DAY" };
  }, [entries, activeTab]);

  const pieData = useMemo(() => {
    const p = activeStats.protein * 4;
    const c = activeStats.carbs * 4;
    const f = activeStats.fat * 9;
    const sum = p + c + f;
    if (sum === 0) return [{ name: "No data yet", value: 1, empty: true }];
    return [
      { name: "Protein", value: p, grams: Math.round(activeStats.protein), color: COLORS.protein, pct: Math.round((p / sum) * 100) },
      { name: "Carbs", value: c, grams: Math.round(activeStats.carbs), color: COLORS.carbs, pct: Math.round((c / sum) * 100) },
      { name: "Fat", value: f, grams: Math.round(activeStats.fat), color: COLORS.fat, pct: Math.round((f / sum) * 100) },
    ];
  }, [activeStats]);

  const compositionPct = useCallback(
    (macro) => pieData.find((d) => d.name.toLowerCase() === macro)?.pct ?? 0,
    [pieData]
  );

  /* ----- today's entries, broken into fixed meal-type sections ----- */
  const todayISO = daysAgoISO(0);
  const todaysEntries = useMemo(() => entries.filter((e) => e.dateISO === todayISO), [entries, todayISO]);

  /* ----- history: does a given day have entries? which day is selected? ----- */
  const historyDayEntries = useMemo(
    () => entries.filter((e) => e.dateISO === selectedHistoryDate),
    [entries, selectedHistoryDate]
  );

  const calendarCells = useMemo(() => {
    const year = calendarMonth.getFullYear();
    const month = calendarMonth.getMonth();
    const firstWeekday = new Date(year, month, 1).getDay();
    const daysInMonth = new Date(year, month + 1, 0).getDate();
    const cells = Array.from({ length: firstWeekday }, () => null);
    for (let day = 1; day <= daysInMonth; day++) {
      const iso = toISODate(new Date(year, month, day));
      cells.push({
        day,
        iso,
        hasData: entries.some((e) => e.dateISO === iso),
        isToday: iso === todayISO,
        isFuture: isoToTimestamp(iso) > isoToTimestamp(todayISO),
      });
    }
    return cells;
  }, [calendarMonth, entries, todayISO]);

  const isCurrentCalendarMonth =
    calendarMonth.getFullYear() === new Date().getFullYear() && calendarMonth.getMonth() === new Date().getMonth();

  /* ----- edit meal (shared by today's log + history) ----- */
  const startEdit = useCallback((entry) => {
    setEditingId(entry.id);
    setEditDraft({
      mealType: entry.mealType,
      raw: entry.raw,
      calories: String(entry.calories),
      protein: String(entry.protein),
      carbs: String(entry.carbs),
      fat: String(entry.fat),
    });
  }, []);

  const cancelEdit = useCallback(() => {
    setEditingId(null);
    setEditDraft(null);
  }, []);

  const saveEdit = useCallback(
    (id) => {
      setEntries((prev) =>
        prev.map((e) =>
          e.id === id
            ? {
                ...e,
                mealType: editDraft.mealType,
                raw: editDraft.raw.trim() || e.raw,
                calories: Math.max(0, Math.round(parseFloat(editDraft.calories) || 0)),
                protein: Math.max(0, Math.round((parseFloat(editDraft.protein) || 0) * 10) / 10),
                carbs: Math.max(0, Math.round((parseFloat(editDraft.carbs) || 0) * 10) / 10),
                fat: Math.max(0, Math.round((parseFloat(editDraft.fat) || 0) * 10) / 10),
              }
            : e
        )
      );
      setEditingId(null);
      setEditDraft(null);
    },
    [editDraft]
  );

  const handleDelete = useCallback((id) => {
    setEntries((prev) => prev.filter((e) => e.id !== id));
    setEditingId((cur) => (cur === id ? null : cur));
  }, []);

  /* ----- log food modal flow ----- */
  const openLogModal = useCallback(() => {
    setLogModalOpen(true);
    setLogStep("select-type");
    setSelectedMealType(null);
    setInputText("");
  }, []);

  const closeLogModal = useCallback(() => {
    if (listening) recognitionRef.current?.stop();
    setListening(false);
    setLogModalOpen(false);
  }, [listening]);

  const pickMealType = useCallback((type) => {
    setSelectedMealType(type);
    setLogStep("input");
  }, []);

  const handleAddFromModal = useCallback(() => {
    const macros = parseMacros(inputText);
    if (!macros || !selectedMealType) return;
    const entry = {
      id: `${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
      dateISO: daysAgoISO(0),
      time: new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }),
      mealType: selectedMealType,
      raw: inputText.trim(),
      ...macros,
    };
    setEntries((prev) => [entry, ...prev]);
    showToast(`${selectedMealType} logged ✓`);
    closeLogModal();
  }, [inputText, selectedMealType, closeLogModal, showToast]);

  /* ----- voice input ----- */
  const toggleListening = useCallback(() => {
    const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;

    if (!SpeechRecognition) {
      showToast("Voice input isn't supported in this browser — use text input instead.");
      return;
    }

    if (listening) {
      recognitionRef.current?.stop();
      setListening(false);
      return;
    }

    const recognition = new SpeechRecognition();
    recognition.lang = "en-US";
    recognition.interimResults = false;
    recognition.maxAlternatives = 1;

    recognition.onresult = (event) => {
      const transcript = event.results[0][0].transcript;
      setInputText((prev) => (prev ? `${prev} ${transcript}` : transcript));
    };
    recognition.onend = () => setListening(false);
    recognition.onerror = (event) => {
      setListening(false);
      if (event.error === "not-allowed" || event.error === "permission-denied" || event.error === "service-not-allowed") {
        showToast("Microphone permission denied — use text input instead.");
      } else if (event.error === "no-speech") {
        showToast("Didn't catch that — try again or use text input.");
      } else {
        showToast("Voice input hit a snag — use text input instead.");
      }
    };

    try {
      recognitionRef.current = recognition;
      recognition.start();
      setListening(true);
    } catch {
      showToast("Couldn't start voice input — use text input instead.");
      setListening(false);
    }
  }, [listening, showToast]);

  const handleKeyDown = (e) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      handleAddFromModal();
    }
  };

  const renderMealTypeSections = (dateEntries) =>
    MEAL_TYPE_ORDER.map((type) => {
      const items = dateEntries.filter((e) => e.mealType === type);
      const subtotal = items.reduce((s, e) => s + e.calories, 0);
      const Icon = MEAL_TYPE_META[type].icon;
      return (
        <div key={type} className="mb-4 last:mb-0">
          <div className="flex items-center justify-between mb-2 px-1">
            <div className="flex items-center gap-2">
              <Icon size={14} style={{ color: MUTED }} />
              <span className="text-xs font-semibold uppercase tracking-wider" style={{ color: TEXT }}>{type}</span>
            </div>
            {items.length > 0 && <span className="font-mono text-[11px]" style={{ color: MUTED }}>{subtotal} kcal</span>}
          </div>
          {items.length === 0 ? (
            <div className="rounded-xl border border-dashed p-3 text-center text-xs" style={{ borderColor: BORDER, color: MUTED }}>
              No {type.toLowerCase()} logged
            </div>
          ) : (
            <div className="space-y-2.5">
              {items.map((entry) => (
                <EntryCard
                  key={entry.id}
                  entry={entry}
                  isEditing={editingId === entry.id}
                  editDraft={editDraft}
                  setEditDraft={setEditDraft}
                  onStartEdit={() => startEdit(entry)}
                  onCancelEdit={cancelEdit}
                  onSaveEdit={() => saveEdit(entry.id)}
                  onDelete={() => handleDelete(entry.id)}
                />
              ))}
            </div>
          )}
        </div>
      );
    });

  return (
    <div className="min-h-screen w-full" style={{ background: BG, color: TEXT }}>
      <div className="mx-auto max-w-md min-h-screen flex flex-col">
        {/* Header */}
        <header className="px-5 pt-6 pb-4">
          <div className="flex items-center gap-2">
            <div className="h-8 w-8 rounded-full flex items-center justify-center" style={{ background: SURFACE, border: `1px solid ${BORDER}` }}>
              <UtensilsCrossed size={16} style={{ color: COLORS.cal }} />
            </div>
            <div>
              <h1 className="text-lg font-bold tracking-tight">Plate.</h1>
              <p className="text-[11px] -mt-0.5" style={{ color: MUTED }}>today's intake, logged as you eat</p>
            </div>
          </div>
        </header>

        {/* Primary actions */}
        <div className="px-5 pb-4 flex gap-2">
          <button
            onClick={openLogModal}
            className="flex-1 flex items-center justify-center gap-1.5 rounded-full py-3 text-sm font-semibold"
            style={{ background: COLORS.cal, color: "#fff" }}
          >
            <Plus size={16} strokeWidth={2.5} />
            Log food
          </button>
          <button
            onClick={() => setHistoryOpen(true)}
            className="flex items-center justify-center gap-1.5 rounded-full px-4 py-3 text-sm font-semibold"
            style={{ background: SURFACE, border: `1px solid ${BORDER}`, color: TEXT }}
          >
            <CalendarDays size={16} />
            History
          </button>
        </div>

        {/* Scrollable content */}
        <div className="flex-1 px-5 pb-10 space-y-6 overflow-y-auto">
          {/* Time-frame tabs */}
          <div className="rounded-full p-1 flex" style={{ background: SURFACE, border: `1px solid ${BORDER}` }}>
            {TABS.map((tab) => {
              const Icon = tab.icon;
              const active = activeTab === tab.key;
              return (
                <button
                  key={tab.key}
                  onClick={() => setActiveTab(tab.key)}
                  className="flex-1 flex items-center justify-center gap-1.5 rounded-full py-2 text-xs font-semibold transition-colors"
                  style={active ? { background: COLORS.cal, color: "#fff" } : { color: MUTED }}
                >
                  <Icon size={13} />
                  {tab.label}
                </button>
              );
            })}
          </div>
          {activeTab !== "daily" && (
            <p className="text-[11px] -mt-4 px-1" style={{ color: MUTED }}>
              Averaged across {activeStats.loggedDays} logged day{activeStats.loggedDays === 1 ? "" : "s"} in this window.
            </p>
          )}

          {/* Calorie dial card */}
          <section className="rounded-2xl p-6 flex flex-col items-center" style={{ background: SURFACE, border: `1px solid ${BORDER}` }}>
            <CalorieDial consumed={activeStats.calories} goal={GOALS.calories} tabLabel={activeStats.rangeLabel} />
          </section>

          {/* Macro bars */}
          <section className="rounded-2xl p-5 space-y-4" style={{ background: SURFACE, border: `1px solid ${BORDER}` }}>
            <div>
              <h2 className="text-xs font-semibold uppercase tracking-widest" style={{ color: MUTED }}>Macros</h2>
              <p className="text-[10px] font-mono mt-0.5" style={{ color: MUTED }}>Target split · 35% protein · 40% carbs · 25% fat</p>
            </div>
            <MacroBar label="Protein" value={activeStats.protein} goal={GOALS.protein} color={COLORS.protein} compositionPct={compositionPct("protein")} />
            <MacroBar label="Carbs" value={activeStats.carbs} goal={GOALS.carbs} color={COLORS.carbs} compositionPct={compositionPct("carbs")} />
            <MacroBar label="Fat" value={activeStats.fat} goal={GOALS.fat} color={COLORS.fat} compositionPct={compositionPct("fat")} />
          </section>

          {/* Donut chart */}
          <section className="rounded-2xl p-5" style={{ background: SURFACE, border: `1px solid ${BORDER}` }}>
            <h2 className="text-xs font-semibold uppercase tracking-widest mb-2" style={{ color: MUTED }}>Calorie split</h2>
            <div className="h-56 relative">
              <ResponsiveContainer width="100%" height="100%">
                <PieChart>
                  <Pie data={pieData} dataKey="value" nameKey="name" innerRadius={62} outerRadius={90} paddingAngle={pieData[0].empty ? 0 : 3} stroke="none">
                    {pieData.map((entry, i) => (
                      <Cell key={i} fill={entry.empty ? BORDER : entry.color} />
                    ))}
                  </Pie>
                  {!pieData[0].empty && <Tooltip content={<DonutTooltip />} />}
                </PieChart>
              </ResponsiveContainer>
              <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
                {pieData[0].empty ? (
                  <span className="text-xs text-center max-w-[100px]" style={{ color: MUTED }}>No data yet</span>
                ) : (
                  <span className="font-mono text-sm" style={{ color: MUTED }}>{Math.round(activeStats.calories).toLocaleString()} kcal</span>
                )}
              </div>
            </div>
            {!pieData[0].empty && (
              <div className="flex justify-center gap-4 mt-2 flex-wrap">
                {pieData.map((d) => (
                  <div key={d.name} className="flex items-center gap-1.5">
                    <span className="h-2 w-2 rounded-full" style={{ background: d.color }} />
                    <span className="text-[11px]" style={{ color: MUTED }}>{d.name} · {d.pct}%</span>
                  </div>
                ))}
              </div>
            )}
          </section>

          {/* Today's meals, broken down by meal type */}
          <section>
            <h2 className="text-xs font-semibold uppercase tracking-widest mb-3 px-1" style={{ color: MUTED }}>Today's meals</h2>
            {renderMealTypeSections(todaysEntries)}
          </section>
        </div>
      </div>

      {/* LOG FOOD MODAL */}
      {logModalOpen && (
        <div className="fixed inset-0 z-50 flex items-end justify-center" style={{ background: "rgba(2,6,23,0.7)" }} onClick={closeLogModal}>
          <div className="w-full max-w-md rounded-t-3xl p-5 pb-8" style={{ background: SURFACE, border: `1px solid ${BORDER}` }} onClick={(e) => e.stopPropagation()}>
            {logStep === "select-type" ? (
              <>
                <div className="flex items-center justify-between mb-4">
                  <h3 className="text-base font-bold">Log a meal</h3>
                  <button onClick={closeLogModal} style={{ color: MUTED }}><X size={18} /></button>
                </div>
                <div className="grid grid-cols-2 gap-3">
                  {MEAL_TYPE_ORDER.map((type) => {
                    const { icon: Icon, blurb } = MEAL_TYPE_META[type];
                    return (
                      <button
                        key={type}
                        onClick={() => pickMealType(type)}
                        className="rounded-2xl p-4 flex flex-col items-start gap-2 text-left"
                        style={{ background: BG, border: `1px solid ${BORDER}` }}
                      >
                        <Icon size={20} style={{ color: COLORS.cal }} />
                        <span className="font-semibold text-sm">{type}</span>
                        <span className="text-[11px]" style={{ color: MUTED }}>{blurb}</span>
                      </button>
                    );
                  })}
                </div>
              </>
            ) : (
              <>
                <div className="flex items-center gap-2 mb-4">
                  <button onClick={() => setLogStep("select-type")} style={{ color: MUTED }}><ChevronLeft size={18} /></button>
                  <h3 className="text-base font-bold">Log {selectedMealType?.toLowerCase()}</h3>
                  <button onClick={closeLogModal} className="ml-auto" style={{ color: MUTED }}><X size={18} /></button>
                </div>
                <div className="rounded-2xl p-3" style={{ background: BG, border: `1px solid ${BORDER}` }}>
                  <textarea
                    autoFocus
                    value={inputText}
                    onChange={(e) => setInputText(e.target.value)}
                    onKeyDown={handleKeyDown}
                    placeholder={`e.g. "3 scrambled eggs and 2 slices of sourdough"`}
                    rows={3}
                    className="w-full resize-none bg-transparent text-sm focus:outline-none"
                    style={{ color: TEXT }}
                  />
                  <div className="flex items-center justify-between mt-2">
                    <button
                      onClick={toggleListening}
                      title={speechSupported ? "Voice input" : "Voice input not supported in this browser"}
                      className="h-9 w-9 rounded-full flex items-center justify-center border transition-colors"
                      style={listening ? { background: COLORS.protein, borderColor: COLORS.protein, color: BG } : { background: SURFACE, borderColor: BORDER, color: MUTED }}
                    >
                      {listening ? <MicOff size={16} /> : <Mic size={16} />}
                    </button>
                    {listening && <span className="text-xs font-mono animate-pulse" style={{ color: COLORS.protein }}>listening…</span>}
                    <button
                      onClick={handleAddFromModal}
                      disabled={!inputText.trim()}
                      className="flex items-center gap-1.5 rounded-full px-4 py-2 text-sm font-semibold disabled:cursor-not-allowed"
                      style={inputText.trim() ? { background: COLORS.cal, color: "#fff" } : { background: BORDER, color: MUTED }}
                    >
                      <Plus size={15} strokeWidth={2.5} />
                      Add to log
                    </button>
                  </div>
                </div>
              </>
            )}
          </div>
        </div>
      )}

      {/* MEAL HISTORY MODAL */}
      {historyOpen && (
        <div className="fixed inset-0 z-50 flex flex-col" style={{ background: BG }}>
          <div className="flex items-center justify-between px-5 pt-6 pb-4" style={{ borderBottom: `1px solid ${BORDER}` }}>
            <h3 className="text-base font-bold">Meal history</h3>
            <button onClick={() => setHistoryOpen(false)} style={{ color: MUTED }}><X size={20} /></button>
          </div>

          <div className="flex-1 overflow-y-auto px-5 py-4">
            {/* Month nav */}
            <div className="flex items-center justify-between mb-3">
              <button
                onClick={() => setCalendarMonth((d) => new Date(d.getFullYear(), d.getMonth() - 1, 1))}
                className="h-8 w-8 rounded-full flex items-center justify-center"
                style={{ background: SURFACE, border: `1px solid ${BORDER}`, color: TEXT }}
              >
                <ChevronLeft size={16} />
              </button>
              <span className="text-sm font-semibold">{calendarMonth.toLocaleDateString([], { month: "long", year: "numeric" })}</span>
              <button
                onClick={() => setCalendarMonth((d) => new Date(d.getFullYear(), d.getMonth() + 1, 1))}
                disabled={isCurrentCalendarMonth}
                className="h-8 w-8 rounded-full flex items-center justify-center disabled:opacity-30"
                style={{ background: SURFACE, border: `1px solid ${BORDER}`, color: TEXT }}
              >
                <ChevronRight size={16} />
              </button>
            </div>

            {/* Weekday headers */}
            <div className="grid grid-cols-7 gap-1 mb-1">
              {["S", "M", "T", "W", "T", "F", "S"].map((d, i) => (
                <div key={i} className="text-center text-[10px] py-1" style={{ color: MUTED }}>{d}</div>
              ))}
            </div>

            {/* Day grid */}
            <div className="grid grid-cols-7 gap-1">
              {calendarCells.map((cell, i) =>
                cell ? (
                  <button
                    key={cell.iso}
                    onClick={() => !cell.isFuture && setSelectedHistoryDate(cell.iso)}
                    disabled={cell.isFuture}
                    className="aspect-square rounded-lg flex flex-col items-center justify-center text-xs relative disabled:cursor-not-allowed"
                    style={{
                      background: cell.iso === selectedHistoryDate ? COLORS.cal : cell.hasData ? "#8B5CF622" : "transparent",
                      color: cell.iso === selectedHistoryDate ? "#fff" : TEXT,
                      border: cell.isToday ? `1px solid ${COLORS.cal}` : "1px solid transparent",
                      opacity: cell.isFuture ? 0.3 : 1,
                    }}
                  >
                    {cell.day}
                    {cell.hasData && cell.iso !== selectedHistoryDate && (
                      <span className="absolute bottom-1 h-1 w-1 rounded-full" style={{ background: COLORS.cal }} />
                    )}
                  </button>
                ) : (
                  <div key={`pad-${i}`} />
                )
              )}
            </div>

            {/* Selected day detail */}
            {selectedHistoryDate && (
              <div className="mt-6">
                <div className="flex items-center justify-between mb-3 px-1">
                  <h4 className="text-sm font-bold">{friendlyDateLabel(selectedHistoryDate)}</h4>
                  {historyDayEntries.length > 0 && (
                    <span className="font-mono text-xs" style={{ color: MUTED }}>
                      {historyDayEntries.reduce((s, e) => s + e.calories, 0)} kcal total
                    </span>
                  )}
                </div>
                {historyDayEntries.length === 0 ? (
                  <div className="rounded-2xl border border-dashed p-6 text-center" style={{ borderColor: BORDER }}>
                    <p className="text-sm" style={{ color: MUTED }}>No meals logged on this day.</p>
                  </div>
                ) : (
                  renderMealTypeSections(historyDayEntries)
                )}
              </div>
            )}
          </div>
        </div>
      )}

      <Toast message={toast} />
    </div>
  );
}
