/* === Home (new top-level Dashboard) ===
   The household command center. Four equal-weight cards in a 2x2 grid:
   Money (personal budget), Habits (per-user), Chores (this week), Meals
   (today). A horizontal strip of pinned brain-dump items sits below.

   Design intent: each card pulls its visual identity from the source
   module. Habits use the BrainCard component (same render as the brain
   dump wall). Chores use the `dash-task-row` pattern from the Overview
   tasks card. Meals use `dash-meal-row`. Recent expenses use the `.txn`
   row format from ExpenseRow. The Dashboard is a digest, not a parallel
   visual system — every row should feel like an extract from its home
   screen. */

function HomeScreen({ state, setState, setOpenModal, setEditingBrainNote, userId, setRoute }) {
  const today = isoDate(TODAY);
  const family = state.family || [];
  const expenses = state._allExpenses || state.expenses || [];
  const monthKey_ = currentMonthKey();
  const monthExpenses = expenses.filter(e => monthKey(e.date) === monthKey_);

  return (
    <div className="home-screen">
      <div className="home-header">
        {(() => {
          const d = new Date(today + 'T00:00');
          const dows = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
          return (
            <div className="home-date-hero">
              <div className="home-date-weekday">{dows[d.getDay()]}</div>
              <div className="home-date-line mono">{MONTH_NAMES[d.getMonth()].toUpperCase()} {d.getDate()}, {d.getFullYear()}</div>
            </div>
          );
        })()}
      </div>

      <HomePinnedStrip
        state={state}
        setState={setState}
        userId={userId}
        setOpenModal={setOpenModal}
        setEditingBrainNote={setEditingBrainNote} />

      <div className="home-grid">
        <HomeMoneyCard state={state} monthExpenses={monthExpenses} setRoute={setRoute} />
        <HomeHabitsCard state={state} setState={setState} userId={userId} setRoute={setRoute} setOpenModal={setOpenModal} setEditingBrainNote={setEditingBrainNote} />
        <HomeChoresCard tasks={state.tasks || []} family={family} setState={setState} setRoute={setRoute} />
        <HomeMealsCard state={state} setRoute={setRoute} />
      </div>
    </div>
  );
}

/* ─── Money card ──────────────────────────────────────────────
   Per-member budget rows (member-chip avatar + amount + small bar) and
   recent expenses using the `.txn` row pattern from ExpenseRow. Days-
   remaining in the head, no precise "remaining" hero number — that
   lives in Overview. */
function HomeMoneyCard({ state, monthExpenses, setRoute }) {
  const family = state.family || [];
  const tags = state.tags || [];
  const today = isoDate(TODAY);
  const yesterdayIso = isoDate(new Date(TODAY.getFullYear(), TODAY.getMonth(), TODAY.getDate() - 1));
  const lastDay = new Date(TODAY.getFullYear(), TODAY.getMonth() + 1, 0).getDate();
  const daysLeft = Math.max(0, lastDay - TODAY.getDate());

  const spentBy = (id) => monthExpenses
    .filter(e => e.memberId === id)
    .reduce((s, e) => s + (e.amount || 0), 0);

  const budgeted = family.filter(m => (m.budget || 0) > 0);

  const recent = [...monthExpenses]
    .sort((a, b) => (a.date < b.date ? 1 : a.date > b.date ? -1 : 0))
    .slice(0, 4);

  return (
    <div className="home-card home-card-money" onClick={() => setRoute && setRoute('dashboard')}>
      <div className="home-card-head">
        <span className="home-card-title">Personal Budget</span>
        <span className="home-card-meta">{daysLeft} {daysLeft === 1 ? 'day' : 'days'} left</span>
      </div>

      {budgeted.length > 0 ? (
        <div className="home-budget-list">
          {budgeted.map(m => {
            const spent = spentBy(m.id);
            const pct = Math.min(100, Math.round((spent / m.budget) * 100));
            const over = spent > m.budget;
            return (
              <div key={m.id} className="home-budget-row">
                <span className="member-chip mini" style={{ background: TAG_COLORS[m.color] }} title={m.name}>{nameInitials(m.name)}</span>
                <div className="home-budget-row-body">
                  <div className="home-budget-row-head">
                    <span className="home-budget-name">{m.name}</span>
                    <span className="home-budget-amount mono">
                      <Money value={spent} /> <span className="muted">/ <Money value={m.budget} /></span>
                    </span>
                  </div>
                  <div className={`home-budget-bar ${over ? 'over' : ''}`}>
                    <div className="home-budget-fill" style={{ width: pct + '%', background: TAG_COLORS[m.color] }} />
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      ) : (
        <div className="home-card-empty">No per-member budgets set yet.</div>
      )}

      <div className="home-recent">
        <div className="home-recent-label eyebrow">Recent</div>
        {recent.length === 0 ? (
          <div className="home-card-empty">No expenses logged this month.</div>
        ) : (
          recent.map(e => {
            const t = tagById(tags, e.tagId);
            const m = e.memberId ? memberById(family, e.memberId) : null;
            const dayLabel = e.date === today
              ? 'Today'
              : e.date === yesterdayIso
                ? 'Yesterday'
                : monthDay(e.date);
            return (
              <div key={e.id} className="txn txn-compact">
                <div className="txn-date">{dayLabel}</div>
                <div>
                  <div className="txn-merchant">{e.merchant || '—'}</div>
                  <div className="txn-meta">
                    {t && <Tag tag={t} />}
                    {m && (
                      <span className="member-chip mini" style={{ background: TAG_COLORS[m.color] }} title={m.name}>{nameInitials(m.name)}</span>
                    )}
                  </div>
                </div>
                <div className="txn-amount expense num"><Money value={e.amount} /></div>
              </div>
            );
          })
        )}
      </div>
    </div>
  );
}

/* ─── Habits card — per-user ──────────────────────────────────
   Filtered to brain-dump habits authored by the current user. Renders
   each habit using the full BrainCard component — same look as on the
   brain-dump wall, so habits feel like an extract, not a parallel UI.
   Capped at 3 habits visible. */
function HomeHabitsCard({ state, setState, userId, setRoute, setOpenModal, setEditingBrainNote }) {
  const bd = state.brainDump || { notes: [], tags: [], pinOrder: [] };
  const habits = (bd.notes || []).filter(n =>
    n.type === 'habit' &&
    !n.archived &&
    (!n.authorId || n.authorId === userId)
  );

  // Show up to 5 habits inline; pager only appears when there's actual
  // overflow. The dashboard card has room for 5 compact rows before it
  // would push the grid out of balance.
  const PER_PAGE = 5;
  const [page, setPage] = React.useState(0);
  const pageCount = Math.max(1, Math.ceil(habits.length / PER_PAGE));
  const safePage = Math.min(page, pageCount - 1);
  const visible = habits.slice(safePage * PER_PAGE, safePage * PER_PAGE + PER_PAGE);

  const handleHabitAction = (id, action) => setState(s => {
    const bd2 = s.brainDump || { notes: [], tags: [], pinOrder: [] };
    const dayKey = isoDate(TODAY);
    const notes = bd2.notes.map(n => {
      if (n.id !== id) return n;
      const history = { ...(n.history || {}) };
      if (action === 'check') {
        if ((history[dayKey] || 0) >= 1) delete history[dayKey];
        else history[dayKey] = 1;
        return { ...n, history };
      }
      if (action === 'inc') {
        history[dayKey] = (history[dayKey] || 0) + 1;
        return { ...n, history };
      }
      if (action === 'timer') {
        if (n.timerStartedAt) {
          const elapsed = Math.max(0, Math.floor((Date.now() - new Date(n.timerStartedAt).getTime()) / 1000));
          history[dayKey] = (history[dayKey] || 0) + elapsed;
          const { timerStartedAt, ...rest } = n;
          return { ...rest, history };
        }
        return { ...n, timerStartedAt: new Date().toISOString() };
      }
      return n;
    });
    return { ...s, brainDump: { ...bd2, notes } };
  });

  const openHabit = (n) => { setEditingBrainNote && setEditingBrainNote(n.id); setOpenModal && setOpenModal('brain-note'); };

  return (
    <div className="home-card home-card-habits">
      <div className="home-card-head">
        <span className="home-card-title">Your habits</span>
        <div className="home-card-head-right">
          {pageCount > 1 && (
            <div className="home-habit-pager">
              <button className="home-habit-pager-btn"
                onClick={() => setPage(p => (p - 1 + pageCount) % pageCount)}
                aria-label="Previous habits">←</button>
              <span className="home-habit-pager-pos mono">{safePage + 1}/{pageCount}</span>
              <button className="home-habit-pager-btn"
                onClick={() => setPage(p => (p + 1) % pageCount)}
                aria-label="Next habits">→</button>
            </div>
          )}
          <button className="home-card-link" onClick={() => setRoute && setRoute('brain')}>Commonplace →</button>
        </div>
      </div>

      {habits.length === 0 ? (
        <div className="home-card-empty">
          No habits yet — head to <button className="link-inline" onClick={() => setRoute && setRoute('brain')}>Commonplace</button> to add one.
        </div>
      ) : (
        <div className="home-habit-rows">
          {visible.map(h => <HomeHabitRow key={h.id} note={h} onAction={handleHabitAction} onOpen={() => openHabit(h)} />)}
        </div>
      )}
    </div>
  );
}

/* Compact habit row for the Dashboard — uses the brain-dump habit
   trigger classes (.brain-habit-trigger, .brain-habit-check) at a
   smaller scale via parent-scoped overrides, so a habit row reads as
   a tight extract of its brain-dump card. */
function HomeHabitRow({ note, onAction, onOpen }) {
  const n = note;
  const [, setTick] = React.useState(0);
  const timerActive = n.mode === 'timer' && !!n.timerStartedAt;
  React.useEffect(() => {
    if (!timerActive) return;
    const id = setInterval(() => setTick(t => t + 1), 1000);
    return () => clearInterval(id);
  }, [timerActive]);

  const target = habitTargetFor(n);
  const todayVal = habitTodayValue(n);
  const runningElapsed = timerActive
    ? Math.max(0, Math.floor((Date.now() - new Date(n.timerStartedAt).getTime()) / 1000))
    : 0;
  const liveVal = n.mode === 'timer' ? todayVal + runningElapsed : todayVal;
  const met = liveVal >= target;
  const streak = habitStreak(n);
  const streakUnit = habitCadence(n) === 'weekly' ? 'w' : 'd';

  const renderTrigger = () => {
    const stop = (e) => e.stopPropagation();
    if (n.mode === 'count') {
      return <button className="brain-habit-trigger plus" onClick={(e) => { stop(e); onAction(n.id, 'inc'); }} aria-label="Log one">+</button>;
    }
    if (n.mode === 'timer') {
      return <button className={`brain-habit-trigger timer${timerActive ? ' running' : ''}`} onClick={(e) => { stop(e); onAction(n.id, 'timer'); }} aria-label={timerActive ? 'Stop timer' : 'Start timer'}>{timerActive ? '■' : '▶'}</button>;
    }
    return <button className={`brain-habit-check${met ? ' on' : ''}`} onClick={(e) => { stop(e); onAction(n.id, 'check'); }} aria-label={met ? 'Mark not done' : 'Mark done'}>{met ? '✓' : ''}</button>;
  };

  const renderReadout = () => {
    if (n.mode === 'count') return <span className="home-habit-readout mono">{liveVal}/{target}</span>;
    if (n.mode === 'timer') return <span className="home-habit-readout mono">{formatHabitSeconds(liveVal)} / {formatHabitSeconds(target)}</span>;
    return <span className={`home-habit-readout mono${met ? ' is-met' : ''}`}>{met ? 'DONE TODAY' : 'TAP TO MARK'}</span>;
  };

  return (
    <div className={`home-habit-row${met ? ' is-met' : ''}`} onClick={onOpen}>
      {renderTrigger()}
      <div className="home-habit-body">
        <div className="home-habit-title">{n.title || '(untitled habit)'}</div>
        <div className="home-habit-meta">
          {renderReadout()}
          {streak > 0 && <span className="home-habit-streak mono">· {streak}{streakUnit} streak</span>}
        </div>
      </div>
    </div>
  );
}

/* ─── Chores card ─────────────────────────────────────────────
   Open chores due this week. Uses the same `.dash-task-row` markup as
   the Overview tasks card (task-check, task-prio, task-due, dash-task-
   member chips) so a chore row reads identical to its render elsewhere.
   Recurring chores roll forward on toggle instead of completing. */
function HomeChoresCard({ tasks, family, setState, setRoute }) {
  const weekStart = weekStartIso(isoDate(TODAY));
  const weekEnd = addDaysIso(weekStart, 6);
  const open = tasks.filter(t => !t.done);
  // Surface both due-this-week chores (recurring or dated) AND undated
  // regular chores the user may have around. Show this-week first so the
  // time-sensitive ones don't get pushed off the cap by an old undated
  // to-do. Skip chores due in a later week — they're not actionable yet.
  const thisWeek = open.filter(t => t.dueDate && t.dueDate >= weekStart && t.dueDate <= weekEnd)
    .sort((a, b) => a.dueDate.localeCompare(b.dueDate));
  const undated = open.filter(t => !t.dueDate);
  const combined = [...thisWeek, ...undated];

  const top = combined.slice(0, 6);
  const remaining = combined.length - top.length;

  const toggleTask = (taskId) => setState(s => {
    const tasks_ = (s.tasks || []).map(t => {
      if (t.id !== taskId) return t;
      if (t.recurrence && !t.done) {
        const nextDue = advanceRecurrence(t.dueDate, t.recurrence.type, t.recurrence.interval);
        return {
          ...t,
          dueDate: nextDue,
          subtasks: (t.subtasks || []).map(st => ({ ...st, done: false })),
        };
      }
      return { ...t, done: !t.done };
    });
    return { ...s, tasks: tasks_ };
  });

  return (
    <div className="home-card home-card-chores">
      <div className="home-card-head">
        <span className="home-card-title">Open chores</span>
        <button className="home-card-link" onClick={() => setRoute && setRoute('tasks')}>Open all →</button>
      </div>
      {combined.length === 0 ? (
        <div className="home-card-empty">
          Nothing on the list. <button className="link-inline" onClick={() => setRoute && setRoute('tasks')}>Add a chore →</button>
        </div>
      ) : (
        <>
          {top.map(t => {
            const due = formatDue(t.dueDate, t.done);
            const member = t.memberId ? family.find(m => m.id === t.memberId) : null;
            const subs = t.subtasks || [];
            const subDone = subs.filter(s => s.done).length;
            const p = t.priority || 'II';
            const tone = p === 'I' ? 'low' : p === 'III' ? 'high' : 'med';
            return (
              <div key={t.id} className={`dash-task-row prio-${tone}`}>
                <button className={`task-check small ${t.done ? 'on' : ''}`}
                  onClick={(e) => { e.stopPropagation(); toggleTask(t.id); }}
                  aria-label={t.done ? 'Mark not done' : 'Mark done'}>
                  {t.done ? '✓' : ''}
                </button>
                <button className="dash-task-title-btn"
                  onClick={() => setRoute && setRoute('tasks')}
                  title="Open in Chores">
                  {t.title}
                </button>
                <div className="dash-task-meta">
                  <span className={`task-prio prio-${tone}`} title={`Priority ${p}`}>{p}</span>
                  {due && <span className={`task-due ${due.tone}`}>{due.label}</span>}
                  {subs.length > 0 && (
                    <span className="muted mono" style={{ fontSize: 10.5 }}>{subDone}/{subs.length}</span>
                  )}
                  {member && (
                    <span className="dash-task-member"
                      style={{ background: TAG_COLORS[member.color] }}
                      title={member.name}>{nameInitials(member.name)}</span>
                  )}
                </div>
              </div>
            );
          })}
          {remaining > 0 && (
            <div className="muted mono" style={{ fontSize: 10.5, marginTop: 6, textAlign: 'right' }}>
              +{remaining} more
            </div>
          )}
        </>
      )}
    </div>
  );
}

/* ─── Meals card ──────────────────────────────────────────────
   Today's three meal slots, rendered with the same `.dash-meal-row`
   pattern the Overview meals card uses (eyebrow meal type + recipe
   name + cost/member meta). Time-of-day highlight (current slot reads
   green) is the one Dashboard-specific touch: breakfast before 11am,
   lunch 11-4, dinner 4-10pm; outside those hours nothing highlights. */
function HomeMealsCard({ state, setRoute }) {
  const { mealPlan = [], recipes = [], family = [], pantry = [] } = state;
  const today = isoDate(TODAY);
  const hour = new Date().getHours();
  const currentSlot = hour < 11 ? 'breakfast'
    : hour < 16 ? 'lunch'
    : hour < 22 ? 'dinner'
    : null;

  const recipeOf = (id) => recipes.find(r => r.id === id);
  const plansByType = {};
  mealPlan.filter(p => p.date === today).forEach(p => { plansByType[p.mealType] = p; });

  return (
    <div className="home-card home-card-meals">
      <div className="home-card-head">
        <span className="home-card-title">Today's meals</span>
        <button className="home-card-link" onClick={() => setRoute && setRoute('meals')}>Open plan →</button>
      </div>

      {MEAL_TYPES.map(mt => {
        const plan = plansByType[mt];
        const recipe = plan && !plan.diningOut && recipeOf(plan.recipeId);
        const member = plan && plan.memberId ? family.find(f => f.id === plan.memberId) : null;
        const isCurrent = currentSlot === mt;
        return (
          <div key={mt} className={`dash-meal-row ${isCurrent ? 'current' : ''}`}>
            <div className="dash-meal-type eyebrow">{MEAL_TYPE_LABELS[mt]}</div>
            <div className="dash-meal-body">
              <span className="dash-meal-name">
                {plan && plan.diningOut ? (
                  <>
                    <span style={{ marginRight: 4 }}>⌖</span>
                    {plan.note || 'Dining out'}
                  </>
                ) : recipe ? (
                  recipe.name
                ) : (
                  <em className="muted">— not planned —</em>
                )}
              </span>
              <div className="dash-meal-meta">
                {recipe && (
                  <span className="num muted" style={{ fontSize: 11 }}>
                    <Money value={recipeCostWithPantry(recipe, pantry)} compact />
                  </span>
                )}
                {member && (
                  <span className="dash-task-member"
                    style={{ background: TAG_COLORS[member.color] }}
                    title={member.name}>{nameInitials(member.name)}</span>
                )}
              </div>
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* ─── Pinned brain-dump strip ─────────────────────────────────
   Horizontal row of pinned cards from brain dump. Reuses BrainCard so
   habits remain tappable inline (check/inc/timer), to-dos remain
   togglable, etc. Cards open the brain-note modal for full editing. */
function HomePinnedStrip({ state, setState, userId, setOpenModal, setEditingBrainNote }) {
  const bd = state.brainDump || { notes: [], tags: [], pinOrder: [] };
  const brainTags = bd.tags || [];
  // Per-card expand state for the "Show more" toggle on long notes — must
  // be declared above any conditional return so hook order stays stable.
  const [expanded, setExpanded] = React.useState({});
  const toggleExpand = (id) => setExpanded(e => ({ ...e, [id]: !e[id] }));
  const visible = (bd.notes || []).filter(n =>
    !n.archived && n.pinned &&
    (n.privacy === 'public' || !n.authorId || n.authorId === userId)
  );

  if (visible.length === 0) return null;

  const order = bd.pinOrder || [];
  const ordered = [...visible].sort((a, b) => {
    const ai = order.indexOf(a.id); const bi = order.indexOf(b.id);
    return (ai < 0 ? 9999 : ai) - (bi < 0 ? 9999 : bi);
  });

  const updateNote = (id, updater) => setState(s => {
    const bd2 = s.brainDump || { notes: [], tags: [], pinOrder: [] };
    return { ...s, brainDump: { ...bd2, notes: bd2.notes.map(n => n.id === id ? updater(n) : n) } };
  });
  const toggleDone = (id) => updateNote(id, n => ({ ...n, done: !n.done }));
  const toggleItem = (id, itemId) => updateNote(id, n => ({
    ...n, items: (n.items || []).map(it => it.id === itemId ? { ...it, done: !it.done } : it),
  }));
  const togglePin = (id) => setState(s => {
    const bd2 = s.brainDump || { notes: [], tags: [], pinOrder: [] };
    const note = bd2.notes.find(n => n.id === id);
    if (!note) return s;
    const willPin = !note.pinned;
    const notes = bd2.notes.map(n => n.id === id ? { ...n, pinned: willPin } : n);
    let pinOrder = (bd2.pinOrder || []).filter(x => x !== id);
    if (willPin) pinOrder = [...pinOrder, id];
    return { ...s, brainDump: { ...bd2, notes, pinOrder } };
  });
  const handleHabitAction = (id, action) => setState(s => {
    const bd2 = s.brainDump || { notes: [], tags: [], pinOrder: [] };
    const dayKey = isoDate(TODAY);
    const notes = bd2.notes.map(n => {
      if (n.id !== id) return n;
      const history = { ...(n.history || {}) };
      if (action === 'check') {
        if ((history[dayKey] || 0) >= 1) delete history[dayKey];
        else history[dayKey] = 1;
        return { ...n, history };
      }
      if (action === 'inc') {
        history[dayKey] = (history[dayKey] || 0) + 1;
        return { ...n, history };
      }
      if (action === 'timer') {
        if (n.timerStartedAt) {
          const elapsed = Math.max(0, Math.floor((Date.now() - new Date(n.timerStartedAt).getTime()) / 1000));
          history[dayKey] = (history[dayKey] || 0) + elapsed;
          const { timerStartedAt, ...rest } = n;
          return { ...rest, history };
        }
        return { ...n, timerStartedAt: new Date().toISOString() };
      }
      return n;
    });
    return { ...s, brainDump: { ...bd2, notes } };
  });

  const onEdit = (n) => { setEditingBrainNote && setEditingBrainNote(n.id); setOpenModal && setOpenModal('brain-note'); };

  return (
    <div className="home-pinned">
      <div className="home-pinned-head mono">
        <span className="brain-pin-diamond on" />
        PINNED
      </div>
      <div className="home-pinned-strip">
        {ordered.map(n => (
          <div key={n.id} className="home-pinned-cell">
            <BrainCard
              note={n}
              tags={brainTags}
              expanded={!!expanded[n.id]}
              onEdit={() => onEdit(n)}
              onTogglePin={() => togglePin(n.id)}
              onToggleDone={() => toggleDone(n.id)}
              onToggleItem={(itemId) => toggleItem(n.id, itemId)}
              onToggleExpand={() => toggleExpand(n.id)}
              onTagClick={() => {}}
              onHabitAction={handleHabitAction} />
          </div>
        ))}
      </div>
    </div>
  );
}

Object.assign(window, { HomeScreen });
