// Dashboard — the hero screen

// ─── Helpers compartilhados de dashboard ────────────────────
function getDayProgress(state) {
  const tasks = (state && state.tasks) || [];
  const habits = (state && state.habits) || [];
  const tasksToday = tasks.filter(t => t.date === 'hoje');
  const tasksDone = tasksToday.filter(t => t.done).length;
  const habitsDone = habits.filter(h => h.done).length;
  const total = tasksToday.length + habits.length;
  const done = tasksDone + habitsDone;
  return { total, done, percent: total > 0 ? (done / total) * 100 : 0 };
}

function getNextEvent(state) {
  const events = (state && state.events) || [];
  const now = new Date();
  const nowMins = now.getHours() * 60 + now.getMinutes();
  const enriched = events.map(e => {
    const startH = Math.floor(e.start || 0);
    const startM = Math.round(((e.start || 0) % 1) * 60);
    return { ...e, startMins: startH * 60 + startM };
  });
  const future = enriched
    .filter(e => e.startMins > nowMins)
    .sort((a, b) => a.startMins - b.startMins);
  return future[0] || null;
}

function fmtRelativeMins(eventStartMins) {
  const now = new Date();
  const nowMins = now.getHours() * 60 + now.getMinutes();
  const diff = eventStartMins - nowMins;
  if (diff <= 0) return 'agora';
  if (diff < 60) return `começa em ${diff} min`;
  if (diff < 60 * 4) {
    const h = Math.floor(diff / 60);
    const m = diff % 60;
    return `começa em ${h}h${m > 0 ? ` ${m}m` : ''}`;
  }
  const startH = Math.floor(eventStartMins / 60);
  const startM = eventStartMins % 60;
  return `começa às ${String(startH).padStart(2, '0')}:${String(startM).padStart(2, '0')}`;
}

// Expor pros outros arquivos (web) sem duplicar
window.cdvGetDayProgress = getDayProgress;
window.cdvGetNextEvent = getNextEvent;
window.cdvFmtRelativeMins = fmtRelativeMins;

// ─── Frase motivacional por período do dia ─────────────────
const CDV_PHRASES = {
  manha: [
    'Comece o dia com uma vitória pequena.',
    'Sua melhor hora é entre 9h e 11h — use bem.',
    'Manhãs são pra prioridades, tardes pra tarefas.',
    'Defina sua vitória do dia agora.',
    'Tarefas curtas antes do café te dão impulso.',
  ],
  tarde: [
    'Foco profundo às 14h rende mais que 2h dispersas.',
    'Você está no ritmo — continue.',
    'Termine 1 tarefa importante antes do fim da tarde.',
    'Faça uma pausa de 5 min se passou 50 focado.',
    'Feito é melhor que perfeito.',
  ],
  noite: [
    'Feche o dia revisando o que conquistou.',
    'Você fez mais do que percebe hoje.',
    'Planeje amanhã antes de dormir.',
    'Um hábito pequeno antes de dormir vira sequência.',
    'Cinco minutos de gratidão antes de descansar.',
  ],
  madrugada: [
    'Descansar também é produtividade.',
    'Sono profundo > 1h extra trabalhando.',
    'Recarregue. Amanhã tem mais.',
  ],
};
function getMotivationalPhrase() {
  const h = new Date().getHours();
  let bucket;
  if (h >= 5 && h < 12) bucket = 'manha';
  else if (h >= 12 && h < 18) bucket = 'tarde';
  else if (h >= 18 && h < 22) bucket = 'noite';
  else bucket = 'madrugada';
  const list = CDV_PHRASES[bucket];
  const day = new Date().getDate();
  return list[day % list.length];
}

// ─── Histórico agregado de hábitos (últimos 7 dias) ────────
function getHabitsSparkData(habits, days = 7) {
  if (!habits || !habits.length) return [];
  const out = [];
  for (let i = 0; i < days; i++) {
    let count = 0;
    habits.forEach(h => {
      const hist = h.history || [];
      const idx = hist.length - days + i;
      if (idx >= 0 && hist[idx]) count++;
    });
    out.push(count);
  }
  // Se todos os pontos são zero, considera "sem dados" e retorna vazio
  const sum = out.reduce((a, b) => a + b, 0);
  return sum > 0 ? out : [];
}

// ─── Meta com prazo mais próximo ───────────────────────────
const CDV_MONTHS = { jan: 0, fev: 1, mar: 2, abr: 3, mai: 4, jun: 5, jul: 6, ago: 7, set: 8, out: 9, nov: 10, dez: 11 };
function parseDeadline(s) {
  if (!s) return null;
  const lower = String(s).toLowerCase().trim();
  // "Dez 2026" / "Jun 2027"
  const m1 = lower.match(/^(jan|fev|mar|abr|mai|jun|jul|ago|set|out|nov|dez)[a-z\.]*\s+(\d{4})$/i);
  if (m1) {
    const mo = CDV_MONTHS[m1[1].slice(0, 3)];
    const yr = parseInt(m1[2], 10);
    if (mo != null && !isNaN(yr)) return new Date(yr, mo + 1, 0); // último dia do mês
  }
  // "1 mês", "3 meses", "1 ano"
  const m2 = lower.match(/(\d+)\s*(m[eê]s|meses|ano|anos)/i);
  if (m2) {
    const n = parseInt(m2[1], 10);
    const d = new Date();
    if (/^m/.test(m2[2])) d.setMonth(d.getMonth() + n);
    else d.setFullYear(d.getFullYear() + n);
    return d;
  }
  return null;
}
function getNearestGoal(state) {
  const goals = (state && state.goals) || [];
  const now = new Date();
  return goals
    .map(g => ({ g, date: parseDeadline(g.deadline) }))
    .filter(x => x.date && x.date > now)
    .sort((a, b) => a.date - b.date)[0] || null;
}
function daysUntil(date) {
  if (!date) return null;
  return Math.max(0, Math.ceil((date - new Date()) / (1000 * 60 * 60 * 24)));
}

window.cdvGetMotivationalPhrase = getMotivationalPhrase;
window.cdvGetHabitsSparkData = getHabitsSparkData;
window.cdvGetNearestGoal = getNearestGoal;
window.cdvDaysUntil = daysUntil;

// ─── Sugestão contextual da Sofia (regras sobre o state) ───
function getSofiaSuggestion(state, opts = {}) {
  const userName = opts.userName || 'você';
  const tasks = (state && state.tasks) || [];
  const habits = (state && state.habits) || [];
  const events = (state && state.events) || [];
  const finance = (state && state.finance) || {};
  const now = new Date();
  const nowMins = now.getHours() * 60 + now.getMinutes();
  const hour = now.getHours();
  const greeting = hour < 12 ? `Bom dia, ${userName}`
    : hour < 18 ? `Boa tarde, ${userName}`
    : `Boa noite, ${userName}`;

  // 1) Tarefas alta prioridade pendentes hoje
  const altaPendentes = tasks.filter(t => t.date === 'hoje' && t.priority === 'alta' && !t.done);
  if (altaPendentes.length > 0) {
    return {
      label: `${greeting} · Sofia sugere`,
      text: `Você tem ${altaPendentes.length} tarefa${altaPendentes.length === 1 ? '' : 's'} de alta prioridade hoje. Que tal começar por "${altaPendentes[0].title}"?`,
      action: { kind: 'route', route: 'tasks', label: 'Ver tarefas' },
    };
  }

  // 2) Próximo evento começando em menos de 60 min
  const nextEv = events
    .map(e => {
      const sh = Math.floor(e.start || 0);
      const sm = Math.round(((e.start || 0) % 1) * 60);
      return { ...e, mins: sh * 60 + sm };
    })
    .filter(e => e.mins > nowMins && e.mins - nowMins < 60)
    .sort((a, b) => a.mins - b.mins)[0];
  if (nextEv) {
    const diff = nextEv.mins - nowMins;
    return {
      label: `${greeting} · Sofia sugere`,
      text: `"${nextEv.title}" começa em ${diff} min. Que tal já preparar o que vai precisar?`,
      action: { kind: 'route', route: 'calendar', label: 'Ver agenda' },
    };
  }

  // 3) Cartão acima de 70% do limite
  if (finance.cartao && finance.cartaoLimite && finance.cartao / finance.cartaoLimite > 0.7) {
    const pct = Math.round((finance.cartao / finance.cartaoLimite) * 100);
    return {
      label: `${greeting} · Alerta financeiro`,
      text: `Seu cartão está em ${pct}% do limite. Quer ver onde estão os maiores gastos do mês?`,
      action: { kind: 'route', route: 'finance', label: 'Ver finanças' },
    };
  }

  // 4) Tarde/noite com hábitos não feitos
  const habitosPendentes = habits.filter(h => !h.done);
  if (hour >= 17 && habitosPendentes.length > 0 && habitosPendentes.length < habits.length) {
    const lista = habitosPendentes.slice(0, 2).map(h => h.name).join(' e ');
    return {
      label: `${greeting} · Sofia sugere`,
      text: `Faltam ${habitosPendentes.length} hábito${habitosPendentes.length === 1 ? '' : 's'} pra fechar o dia: ${lista}. Bora?`,
      action: { kind: 'route', route: 'habits', label: 'Ver hábitos' },
    };
  }

  // 5) Tarefa com horário próximo (próximas 2h)
  const taskProx = tasks
    .filter(t => t.date === 'hoje' && !t.done && t.time && /^\d{1,2}:\d{2}$/.test(t.time))
    .map(t => {
      const [h, m] = t.time.split(':').map(Number);
      return { ...t, mins: h * 60 + m };
    })
    .filter(t => t.mins > nowMins && t.mins - nowMins < 120)
    .sort((a, b) => a.mins - b.mins)[0];
  if (taskProx) {
    const diff = taskProx.mins - nowMins;
    return {
      label: `${greeting} · Sofia sugere`,
      text: `"${taskProx.title}" começa em ${diff < 60 ? `${diff} min` : `${Math.floor(diff / 60)}h${diff % 60 > 0 ? ` ${diff % 60}m` : ''}`}. Iniciar um foco profundo?`,
      action: { kind: 'focus', label: 'Iniciar foco' },
    };
  }

  // 6) Manhã com progresso muito baixo do dia
  const tasksToday = tasks.filter(t => t.date === 'hoje');
  const total = tasksToday.length + habits.length;
  const done = tasksToday.filter(t => t.done).length + habits.filter(h => h.done).length;
  const pct = total > 0 ? (done / total) : 0;
  if (hour < 12 && pct < 0.2 && total > 0) {
    return {
      label: `${greeting} · Sofia sugere`,
      text: 'Comece o dia com uma vitória rápida: marque um hábito ou conclua uma tarefa curta antes do almoço.',
      action: { kind: 'route', route: 'tasks', label: 'Ver tarefas' },
    };
  }

  // 7) Meta com prazo próximo e progresso < 50%
  const nearest = getNearestGoal(state);
  if (nearest && nearest.g.progress < 50) {
    const days = daysUntil(nearest.date);
    return {
      label: `${greeting} · Sofia sugere`,
      text: `Sua meta "${nearest.g.title}" está em ${nearest.g.progress}% e vence em ${days} dias. Que tal avançar uma etapa hoje?`,
      action: { kind: 'route', route: 'goals', label: 'Ver metas' },
    };
  }

  // 8) Default: tudo em dia
  return {
    label: `${greeting} · Sofia`,
    text: 'Tudo em dia por aqui ✨ Que tal revisar suas metas ativas ou planejar amanhã?',
    action: { kind: 'route', route: 'goals', label: 'Ver metas' },
  };
}
window.cdvGetSofiaSuggestion = getSofiaSuggestion;

// ─── Sparkline ──────────────────────────────────────────────
const Sparkline = ({ data, color, height = 22, width = 60 }) => {
  if (!data || data.length < 2) return null;
  const max = Math.max(...data, 1);
  const min = Math.min(...data, 0);
  const range = (max - min) || 1;
  const points = data.map((v, i) => {
    const x = (i / (data.length - 1)) * width;
    const y = height - ((v - min) / range) * (height - 2) - 1;
    return `${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(' ');
  const lastX = width;
  const lastY = height - ((data[data.length - 1] - min) / range) * (height - 2) - 1;
  return (
    <svg width={width} height={height} style={{ display: 'block', overflow: 'visible' }}>
      <polyline points={points} fill="none" stroke={color} strokeWidth={1.6}
        strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={lastX} cy={lastY} r={2.2} fill={color} />
    </svg>
  );
};
window.Sparkline = Sparkline;

// ─── Anel animado de progresso do dia ───────────────────────
const DayProgressRing = ({ percent, size = 64, stroke = 6, idSuffix = 'm' }) => {
  const target = Math.max(0, Math.min(100, percent || 0));
  const [shown, setShown] = React.useState(0);
  React.useEffect(() => {
    let raf;
    const startTime = Date.now();
    const duration = 900;
    const startVal = 0;
    const tick = () => {
      const elapsed = Date.now() - startTime;
      const t = Math.min(elapsed / duration, 1);
      const eased = 1 - Math.pow(1 - t, 3);
      setShown(startVal + (target - startVal) * eased);
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target]);
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const offset = c * (1 - shown / 100);
  const uid = `dpr-grad-${idSuffix}-${size}`;
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <defs>
          <linearGradient id={uid} x1="0" y1="0" x2="1" y2="1">
            <stop offset="0%" stopColor="#C9B5FF" />
            <stop offset="50%" stopColor="#9D7AFF" />
            <stop offset="100%" stopColor="#FF8FB1" />
          </linearGradient>
        </defs>
        <circle cx={size/2} cy={size/2} r={r}
          stroke={CDV.surfaceHi} strokeWidth={stroke} fill="none" />
        <circle cx={size/2} cy={size/2} r={r}
          stroke={`url(#${uid})`} strokeWidth={stroke} fill="none"
          strokeLinecap="round" strokeDasharray={c} strokeDashoffset={offset} />
      </svg>
      <div style={{
        position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontSize: size > 70 ? 18 : 14, fontWeight: 700, color: CDV.text, letterSpacing: -0.3,
        backgroundImage: 'linear-gradient(135deg, #C9B5FF, #FF8FB1)',
        WebkitBackgroundClip: 'text', backgroundClip: 'text',
        WebkitTextFillColor: 'transparent', color: 'transparent',
      }}>
        {Math.round(shown)}%
      </div>
    </div>
  );
};

// ─── Card de sugestão da Sofia ─────────────────────────────
const SofiaSuggestionCard = ({ state, userName, onOpenAI, onAction, onDismiss }) => {
  const sug = getSofiaSuggestion(state, { userName });
  return (
    <div onClick={onOpenAI} style={{
      padding: 18, borderRadius: 22, position: 'relative', overflow: 'hidden',
      background: 'linear-gradient(135deg, rgba(177,151,252,0.18), rgba(255,143,177,0.10))',
      border: `1px solid ${CDV.strokeHi}`, cursor: 'pointer',
    }}>
      <div style={{
        position: 'absolute', top: -20, right: -20, width: 140, height: 140, borderRadius: 99,
        background: 'radial-gradient(circle, rgba(177,151,252,0.4), transparent 70%)',
        filter: 'blur(20px)',
      }} />
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12, position: 'relative' }}>
        <div style={{
          width: 38, height: 38, borderRadius: 12, background: CDV.brandGrad,
          display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', flexShrink: 0,
          boxShadow: '0 6px 20px -4px rgba(177,151,252,0.5)',
        }}>
          <Icon name="sparkle" size={20} />
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 11, color: CDV.brand, fontWeight: 700, letterSpacing: 0.6, textTransform: 'uppercase' }}>
            {sug.label}
          </div>
          <div style={{ fontSize: 15, color: CDV.text, marginTop: 4, lineHeight: 1.4, fontWeight: 500 }}>
            {sug.text}
          </div>
          <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
            <button onClick={(e) => { e.stopPropagation(); onAction && onAction(sug.action); }} style={{
              background: CDV.text, color: '#000', border: 'none', padding: '8px 14px',
              borderRadius: 99, fontSize: 12, fontWeight: 600, fontFamily: 'inherit',
            }}>{(sug.action && sug.action.label) || 'Aceitar'}</button>
            <button onClick={(e) => { e.stopPropagation(); onDismiss && onDismiss(); }} style={{
              background: 'transparent', color: CDV.textDim, border: 'none', padding: '8px 14px',
              borderRadius: 99, fontSize: 12, fontWeight: 600, fontFamily: 'inherit',
            }}>Não agora</button>
          </div>
        </div>
      </div>
    </div>
  );
};

const DashboardScreen = ({ state, setState, openAI, navigate, showToast, user, profile }) => {
  const { tasks, habits, finance, xp, level, streak } = state;
  const tasksToday = tasks.filter(t => t.date === 'hoje');
  const tasksDone = tasksToday.filter(t => t.done).length;
  const habitsDone = habits.filter(h => h.done).length;
  const dia = new Date().toLocaleDateString('pt-BR', { weekday: 'long', day: 'numeric', month: 'long' });
  // Resolve nome do usuário (user → profile → state → fallback)
  const rawName = (user && user.name)
    || (profile && profile.name)
    || (state.profile && state.profile.name)
    || (user && user.email && user.email.split('@')[0])
    || 'você';
  const userName = String(rawName).trim().split(/\s+/)[0];
  const [showFocus, setShowFocus] = React.useState(false);
  const dayProgress = getDayProgress(state);
  const nextEvent = getNextEvent(state);

  const dispatchIntent = (intent) => {
    if (intent === 'new-task') {
      navigate('tasks');
      setTimeout(() => window.dispatchEvent(new CustomEvent('cdv:open-new-task')), 60);
    } else if (intent === 'new-transaction') {
      navigate('finance');
      setTimeout(() => window.dispatchEvent(new CustomEvent('cdv:open-new-transaction')), 60);
    } else if (intent === 'new-habit') {
      navigate('habits');
      setTimeout(() => window.dispatchEvent(new CustomEvent('cdv:open-new-habit')), 60);
    }
  };

  const toggleTask = (id) => {
    setState(s => ({
      ...s,
      tasks: s.tasks.map(t => {
        if (t.id !== id) return t;
        const nextDone = !t.done;
        const today = new Date().toISOString().slice(0, 10);
        return {
          ...t,
          done: nextDone,
          lastCompletedAt: nextDone && t.recurrence ? today : t.lastCompletedAt,
        };
      })
    }));
    showToast('Tarefa atualizada');
  };
  const toggleHabit = (id) => {
    setState(s => ({ ...s, habits: s.habits.map(h => h.id === id ? { ...h, done: !h.done, current: h.done ? Math.max(0, h.current - 1) : Math.min(h.target, h.current + 1) } : h) }));
    showToast('Hábito marcado');
  };

  return (
    <div style={{ paddingBottom: 110 }}>
      {/* Greeting + day progress */}
      <div style={{ padding: '8px 22px 16px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 14 }}>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 12, color: CDV.textMuted, fontWeight: 600, letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: 2 }}>
              {dia}
            </div>
            <div style={{ fontSize: 26, fontWeight: 700, letterSpacing: -0.5, lineHeight: 1.15 }}>
              {(() => { const h = new Date().getHours(); return h < 12 ? 'Bom dia' : h < 18 ? 'Boa tarde' : 'Boa noite'; })()}, <span style={{ background: CDV.brandGrad, WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' }}>{userName.charAt(0).toUpperCase() + userName.slice(1)}</span>
            </div>
            <div style={{
              fontSize: 12, color: CDV.textDim, marginTop: 6, lineHeight: 1.4,
              display: 'flex', alignItems: 'center', gap: 5,
            }}>
              <Icon name="sparkle" size={11} color={CDV.brand} />
              {getMotivationalPhrase()}
            </div>
          </div>
          {/* Anel de progresso + avatar */}
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, flexShrink: 0 }}>
            <div onClick={() => navigate('profile')} style={{ position: 'relative', cursor: 'pointer' }}>
              <DayProgressRing percent={dayProgress.percent} size={68} stroke={5} />
              {/* mini avatar dot */}
              <div style={{
                position: 'absolute', top: -2, right: -2, width: 16, height: 16, borderRadius: 99,
                background: 'linear-gradient(135deg, #FFB547, #FF7A6B)',
                border: `2px solid ${CDV.bg}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 8, fontWeight: 700, color: '#fff',
              }}>{(userName || 'L').charAt(0).toUpperCase()}</div>
            </div>
            <div style={{ fontSize: 9, color: CDV.textDim, fontWeight: 600, letterSpacing: 0.4, textTransform: 'uppercase', textAlign: 'center', maxWidth: 80 }}>
              Progresso do dia
            </div>
          </div>
        </div>
      </div>

      {/* Sofia — sugestão dinâmica baseada no state */}
      <div style={{ padding: '0 22px 18px' }}>
        <SofiaSuggestionCard
          state={state}
          userName={userName}
          onOpenAI={openAI}
          onAction={(action) => {
            if (!action) return;
            if (action.kind === 'route' && action.route) {
              navigate(action.route);
            } else if (action.kind === 'focus') {
              setShowFocus(true);
            }
          }}
          onDismiss={() => showToast('Ok, deixo pra próxima ✨')}
        />
      </div>

      {/* A seguir + Atalhos rápidos */}
      <div style={{ padding: '0 22px 18px', display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 10 }}>
        <NextUpCard event={nextEvent} onClick={() => navigate('calendar')} />
        <DashShortcuts onDispatch={dispatchIntent} />
      </div>

      {/* Stats grid */}
      <div style={{ padding: '0 22px 18px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <StatTile
          label="Tarefas de hoje"
          big={`${tasksDone}/${tasksToday.length}`}
          extra="3 prioritárias"
          ring={<ProgressRing percent={(tasksDone / Math.max(1, tasksToday.length)) * 100} color={CDV.brand} size={42} stroke={4}>
            <Icon name="check" size={14} color={CDV.brand} />
          </ProgressRing>}
          onClick={() => navigate('tasks')}
        />
        <StatTile
          label="Saldo do mês"
          big={`R$ ${finance.saldo.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}`}
          extra={<><span style={{ color: CDV.mint }}>↗ 12%</span> vs mês passado</>}
          icon="wallet"
          iconColor={CDV.mint}
          onClick={() => navigate('finance')}
        />
        <StatTile
          label="Hábitos do dia"
          big={`${habitsDone}/${habits.length}`}
          extra={`${streak} dias seguidos 🔥`}
          ring={<ProgressRing percent={(habitsDone / habits.length) * 100} color={CDV.flame} size={42} stroke={4}>
            <Icon name="flame" size={14} color={CDV.flame} />
          </ProgressRing>}
          sparkData={getHabitsSparkData(habits)}
          sparkColor={CDV.flame}
          onClick={() => navigate('habits')}
        />
        <StatTile
          label="Nível atual"
          big={`Nv. ${level}`}
          extra={`${xp.toLocaleString('pt-BR')} XP · próx. ${(2400 - xp).toLocaleString('pt-BR')}`}
          icon="trophy"
          iconColor={CDV.amber}
          onClick={() => navigate('achievements')}
        />
      </div>

      {/* Quick actions complementares (voz + foco) */}
      <div style={{ padding: '0 22px 18px' }}>
        <div style={{ display: 'flex', gap: 8, overflowX: 'auto' }}>
          <QuickAction icon="mic" label="Por voz" color={CDV.brand} onClick={openAI} />
          <QuickAction icon="pomodoro" label="Foco" color={CDV.coral} onClick={() => setShowFocus(true)} />
          <QuickAction icon="arrowUp" label="Receita" color={CDV.mint} onClick={() => navigate('finance')} />
        </div>
      </div>

      {/* Today's agenda */}
      <SectionHeader title="Próximas na agenda" action="Ver tudo →" onAction={() => navigate('calendar')} />
      <div style={{ padding: '0 22px 18px', display: 'flex', flexDirection: 'column', gap: 8 }}>
        {tasksToday.filter(t => !t.done).slice(0, 3).map(t => (
          <TaskInlineRow key={t.id} task={t} onToggle={toggleTask} />
        ))}
      </div>

      {/* Habits today */}
      <SectionHeader title="Hábitos de hoje" action="Tudo →" onAction={() => navigate('habits')} />
      <div style={{ padding: '0 22px 18px', display: 'flex', gap: 10, overflowX: 'auto' }}>
        {habits.map(h => (
          <HabitChip key={h.id} habit={h} onToggle={toggleHabit} />
        ))}
      </div>

      {/* Active goal */}
      {state.goals && state.goals.length > 0 && (
        <>
          <SectionHeader title="Sua meta principal" action="Todas →" onAction={() => navigate('goals')} />
          <div style={{ padding: '0 22px 8px' }}>
            <GoalHeroCard goal={state.goals[0]} onClick={() => navigate('goals')} />
          </div>
        </>
      )}

      {/* Meta com prazo mais próximo (se for diferente da principal) */}
      <NearestGoalWidget state={state} onClick={() => navigate('goals')} />

      <Sheet open={showFocus} onClose={() => setShowFocus(false)} title="Modo Foco · Pomodoro">
        <PomodoroTimer onFinish={() => { showToast && showToast('Pomodoro concluído ✨'); setShowFocus(false); }} />
      </Sheet>
    </div>
  );
};

// ── Widget "Meta com prazo mais próximo" ────────────────────
const NearestGoalWidget = ({ state, onClick }) => {
  const nearest = getNearestGoal(state);
  if (!nearest) return null;
  // Se for igual à meta principal já exibida, não duplica
  const principal = (state.goals && state.goals[0]) || null;
  if (principal && nearest.g.id === principal.id) return null;
  const g = nearest.g;
  const days = daysUntil(nearest.date);
  const catColor = (window.GOAL_CAT_COLOR && window.GOAL_CAT_COLOR[g.category]) ||
    (g.category === 'financeiro' ? CDV.mint : g.category === 'saude' ? CDV.coral : g.category === 'viagem' ? '#FF8FB1' : CDV.sky);
  return (
    <>
      <SectionHeader title="Prazo mais próximo" action="Ver metas →" onAction={onClick} />
      <div style={{ padding: '0 22px 18px' }}>
        <div onClick={onClick} style={{
          padding: 16, paddingLeft: 18, borderRadius: 18,
          background: `linear-gradient(135deg, ${catColor}14 0%, ${catColor}06 35%, ${CDV.surface} 100%)`,
          border: `1px solid ${catColor}30`,
          position: 'relative', overflow: 'hidden', cursor: 'pointer',
          boxShadow: `0 6px 18px -10px ${catColor}55`,
        }}>
          <div style={{
            position: 'absolute', top: -40, right: -40, width: 140, height: 140, borderRadius: 99,
            background: `radial-gradient(circle, ${catColor}55, transparent 60%)`,
            filter: 'blur(24px)', opacity: 0.55, pointerEvents: 'none',
          }} />
          <div style={{
            position: 'absolute', left: 0, top: 16, bottom: 16, width: 3, borderRadius: 99,
            background: `linear-gradient(180deg, ${catColor}, ${catColor}40)`,
            boxShadow: `0 0 12px ${catColor}80`,
          }} />
          <div style={{ position: 'relative', display: 'flex', alignItems: 'flex-start', gap: 12 }}>
            <div style={{
              width: 40, height: 40, borderRadius: 12, flexShrink: 0,
              background: `linear-gradient(135deg, ${catColor}38, ${catColor}14)`,
              border: `1px solid ${catColor}30`,
              display: 'flex', alignItems: 'center', justifyContent: 'center', color: catColor,
              boxShadow: `0 6px 16px -6px ${catColor}80`,
            }}><Icon name="target" size={18} /></div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 10, color: catColor, fontWeight: 700, letterSpacing: 0.5, textTransform: 'uppercase' }}>
                {g.category}
              </div>
              <div style={{ fontSize: 14, fontWeight: 600, color: CDV.text, marginTop: 3, lineHeight: 1.25 }}>
                {g.title}
              </div>
              <div style={{ marginTop: 10 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                  <div style={{ fontSize: 11, color: CDV.textDim }}>{g.progress}% concluído</div>
                  <div style={{ fontSize: 11, color: catColor, fontWeight: 600 }}>
                    {days === 0 ? 'vence hoje' : days === 1 ? 'vence amanhã' : `${days} dias restantes`}
                  </div>
                </div>
                <ProgressBar percent={g.progress} color={catColor} height={5} />
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

// ── Pomodoro Timer ──────────────────────────────────────────
const PomodoroTimer = ({ onFinish }) => {
  const FOCUS = 25 * 60;
  const BREAK = 5 * 60;
  const [mode, setMode] = React.useState('focus'); // focus | break
  const [remaining, setRemaining] = React.useState(FOCUS);
  const [running, setRunning] = React.useState(false);
  const [cycles, setCycles] = React.useState(0);
  const intervalRef = React.useRef(null);

  React.useEffect(() => {
    if (!running) return;
    intervalRef.current = setInterval(() => {
      setRemaining(r => {
        if (r <= 1) {
          clearInterval(intervalRef.current);
          if (mode === 'focus') {
            setCycles(c => c + 1);
            setMode('break');
            setRunning(false);
            onFinish && onFinish();
            return BREAK;
          } else {
            setMode('focus');
            setRunning(false);
            return FOCUS;
          }
        }
        return r - 1;
      });
    }, 1000);
    return () => clearInterval(intervalRef.current);
  }, [running, mode]);

  const reset = () => {
    setRunning(false);
    setRemaining(mode === 'focus' ? FOCUS : BREAK);
  };

  const total = mode === 'focus' ? FOCUS : BREAK;
  const pct = ((total - remaining) / total) * 100;
  const mm = String(Math.floor(remaining / 60)).padStart(2, '0');
  const ss = String(remaining % 60).padStart(2, '0');
  const tint = mode === 'focus' ? CDV.coral : CDV.mint;

  return (
    <div style={{ padding: '20px 24px 36px', textAlign: 'center' }}>
      <div style={{ fontSize: 11, color: tint, fontWeight: 700, letterSpacing: 0.6, textTransform: 'uppercase' }}>
        {mode === 'focus' ? 'Foco profundo · 25 min' : 'Pausa curta · 5 min'}
      </div>

      <div style={{ position: 'relative', width: 220, height: 220, margin: '24px auto 8px' }}>
        <svg width={220} height={220} style={{ transform: 'rotate(-90deg)' }}>
          <circle cx={110} cy={110} r={100} stroke={CDV.surfaceHi} strokeWidth={10} fill="none" />
          <circle cx={110} cy={110} r={100} stroke={tint} strokeWidth={10} fill="none"
            strokeDasharray={2 * Math.PI * 100}
            strokeDashoffset={2 * Math.PI * 100 * (1 - pct / 100)}
            strokeLinecap="round"
            style={{ transition: 'stroke-dashoffset 1s linear' }} />
        </svg>
        <div style={{
          position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',
          alignItems: 'center', justifyContent: 'center',
        }}>
          <div style={{ fontSize: 48, fontWeight: 700, color: CDV.text, letterSpacing: -1, fontFamily: 'inherit' }}>{mm}:{ss}</div>
          <div style={{ fontSize: 12, color: CDV.textDim, marginTop: 4 }}>{cycles} ciclo{cycles === 1 ? '' : 's'} hoje</div>
        </div>
      </div>

      <div style={{ display: 'flex', gap: 10, marginTop: 22, justifyContent: 'center' }}>
        <button onClick={reset} style={{
          width: 54, height: 54, borderRadius: 99, background: CDV.surfaceHi,
          border: `1px solid ${CDV.stroke}`, color: CDV.textDim,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}><Icon name="refresh" size={20} /></button>
        <button onClick={() => setRunning(r => !r)} style={{
          height: 54, padding: '0 30px', borderRadius: 99,
          background: running ? CDV.surfaceHi2 : CDV.brandGrad,
          border: running ? `1px solid ${CDV.strokeHi}` : 'none',
          color: '#fff', fontWeight: 600, fontSize: 15, fontFamily: 'inherit',
          minWidth: 140,
        }}>{running ? 'Pausar' : 'Iniciar'}</button>
        <button onClick={() => { setRunning(false); setMode(m => m === 'focus' ? 'break' : 'focus'); setRemaining(mode === 'focus' ? BREAK : FOCUS); }} style={{
          width: 54, height: 54, borderRadius: 99, background: CDV.surfaceHi,
          border: `1px solid ${CDV.stroke}`, color: CDV.textDim,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}><Icon name="arrowRight" size={18} /></button>
      </div>

      <div style={{ marginTop: 18, fontSize: 12, color: CDV.textMuted }}>
        Sem distrações · O cronômetro segue mesmo se fechar este painel
      </div>
    </div>
  );
};

// ── Card "A seguir" ────────────────────────────────────────
const NextUpCard = ({ event, onClick }) => {
  const empty = !event;
  const c = CDV.brand;
  return (
    <div onClick={onClick} style={{
      padding: 14, paddingLeft: 16, borderRadius: 16, cursor: 'pointer',
      background: empty
        ? `linear-gradient(135deg, ${CDV.mint}10 0%, ${CDV.surface} 60%)`
        : `linear-gradient(135deg, ${(event.color || c)}1a 0%, ${(event.color || c)}06 35%, ${CDV.surface} 100%)`,
      border: `1px solid ${(empty ? CDV.mint : (event.color || c))}30`,
      position: 'relative', overflow: 'hidden', minHeight: 96,
      boxShadow: `0 4px 14px -10px ${(empty ? CDV.mint : (event.color || c))}55`,
    }}>
      <div style={{
        position: 'absolute', left: 0, top: 14, bottom: 14, width: 3, borderRadius: 99,
        background: `linear-gradient(180deg, ${(empty ? CDV.mint : (event.color || c))}, ${(empty ? CDV.mint : (event.color || c))}40)`,
        boxShadow: `0 0 10px ${(empty ? CDV.mint : (event.color || c))}80`,
      }} />
      <div style={{ position: 'relative', display: 'flex', alignItems: 'flex-start', gap: 10 }}>
        <div style={{
          width: 34, height: 34, borderRadius: 10,
          background: `linear-gradient(135deg, ${(empty ? CDV.mint : (event.color || c))}38, ${(empty ? CDV.mint : (event.color || c))}14)`,
          border: `1px solid ${(empty ? CDV.mint : (event.color || c))}30`, flexShrink: 0,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: `0 6px 14px -6px ${(empty ? CDV.mint : (event.color || c))}80`,
        }}>
          <Icon name={empty ? 'check' : 'calendar'} size={16} color={empty ? CDV.mint : (event.color || c)} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 10, color: (empty ? CDV.mint : (event.color || c)), fontWeight: 700, letterSpacing: 0.5, textTransform: 'uppercase' }}>
            A seguir
          </div>
          {empty ? (
            <>
              <div style={{ fontSize: 13, fontWeight: 600, color: CDV.text, marginTop: 4, lineHeight: 1.3 }}>
                Nada na agenda agora
              </div>
              <div style={{ fontSize: 11, color: CDV.textDim, marginTop: 2 }}>
                aproveite o tempo livre
              </div>
            </>
          ) : (
            <>
              <div style={{ fontSize: 13, fontWeight: 600, color: CDV.text, marginTop: 4, lineHeight: 1.3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                {event.title}
              </div>
              <div style={{ fontSize: 11, color: CDV.textDim, marginTop: 2, display: 'flex', alignItems: 'center', gap: 5 }}>
                <Icon name="clock" size={10} /> {fmtRelativeMins(event.startMins)}
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
};

// ── 3 atalhos rápidos do dashboard ─────────────────────────
const DashShortcuts = ({ onDispatch }) => {
  const items = [
    { id: 'new-task', icon: 'plus', label: 'Tarefa', color: CDV.brand },
    { id: 'new-transaction', icon: 'wallet', label: 'Gasto', color: CDV.coral },
    { id: 'new-habit', icon: 'flame', label: 'Hábito', color: CDV.flame },
  ];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
      {items.map(it => (
        <button key={it.id} onClick={() => onDispatch(it.id)} style={{
          padding: '10px 6px', borderRadius: 14,
          background: `linear-gradient(135deg, ${it.color}1a 0%, ${CDV.surface} 70%)`,
          border: `1px solid ${it.color}30`,
          color: CDV.text, fontFamily: 'inherit',
          display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5,
          cursor: 'pointer', position: 'relative', overflow: 'hidden',
          boxShadow: `0 4px 12px -10px ${it.color}40`,
        }}>
          <div style={{
            width: 32, height: 32, borderRadius: 10,
            background: `linear-gradient(135deg, ${it.color}38, ${it.color}14)`,
            border: `1px solid ${it.color}30`,
            display: 'flex', alignItems: 'center', justifyContent: 'center', color: it.color,
            boxShadow: `0 6px 14px -6px ${it.color}80, inset 0 0 0 1px rgba(255,255,255,0.06)`,
          }}><Icon name={it.icon} size={14} /></div>
          <div style={{ fontSize: 10, fontWeight: 700, color: CDV.text, letterSpacing: 0.3 }}>{it.label}</div>
        </button>
      ))}
    </div>
  );
};

// ── Stat tile (premium) ────────────────────────────────────
const StatTile = ({ label, big, extra, ring, icon, iconColor, onClick, sparkData, sparkColor }) => {
  const c = iconColor || CDV.brand;
  const [pressed, setPressed] = React.useState(false);
  return (
    <button
      onClick={onClick}
      onTouchStart={() => setPressed(true)}
      onTouchEnd={() => setPressed(false)}
      onMouseDown={() => setPressed(true)}
      onMouseUp={() => setPressed(false)}
      onMouseLeave={() => setPressed(false)}
      style={{
        background: `linear-gradient(135deg, ${c}1a 0%, ${c}06 35%, ${CDV.surface} 100%)`,
        border: `1px solid ${c}30`,
        borderRadius: CDV.r.xl,
        padding: 16, paddingLeft: 18, textAlign: 'left', color: CDV.text, fontFamily: 'inherit',
        display: 'flex', flexDirection: 'column', gap: 10, minHeight: 112,
        position: 'relative', overflow: 'hidden',
        transform: pressed ? 'scale(0.98)' : 'scale(1)',
        transition: 'transform .15s, box-shadow .2s',
        boxShadow: `0 6px 18px -10px ${c}40, 0 0 0 1px ${c}10 inset`,
        cursor: onClick ? 'pointer' : 'default',
      }}
    >
      {/* Glow blob no canto superior direito */}
      <div style={{
        position: 'absolute', top: -40, right: -40, width: 130, height: 130, borderRadius: 99,
        background: `radial-gradient(circle, ${c}55, transparent 60%)`,
        filter: 'blur(22px)', opacity: 0.6, pointerEvents: 'none',
      }} />
      {/* Barra lateral */}
      <div style={{
        position: 'absolute', left: 0, top: 14, bottom: 14, width: 3, borderRadius: 99,
        background: `linear-gradient(180deg, ${c}, ${c}40)`,
        boxShadow: `0 0 14px ${c}80`,
      }} />

      <div style={{ position: 'relative', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ fontSize: 10, color: c, fontWeight: 700, letterSpacing: 0.5, textTransform: 'uppercase' }}>{label}</div>
        {ring}
        {icon && !ring && (
          <div style={{
            width: 30, height: 30, borderRadius: 9,
            background: `linear-gradient(135deg, ${c}38, ${c}14)`,
            border: `1px solid ${c}30`,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: `0 6px 16px -6px ${c}80, inset 0 0 0 1px rgba(255,255,255,0.06)`,
          }}>
            <Icon name={icon} size={14} color={c} />
          </div>
        )}
      </div>
      <div style={{
        position: 'relative',
        fontSize: 26, fontWeight: 700, letterSpacing: -0.6,
        backgroundImage: `linear-gradient(135deg, ${CDV.text} 0%, ${c} 130%)`,
        WebkitBackgroundClip: 'text', backgroundClip: 'text',
        WebkitTextFillColor: 'transparent', color: 'transparent',
        lineHeight: 1.05,
      }}>{big}</div>
      <div style={{ position: 'relative', display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 8 }}>
        <div style={{ fontSize: 11, color: CDV.textDim, fontWeight: 500 }}>{extra}</div>
        {sparkData && sparkData.length >= 2 && (
          <Sparkline data={sparkData} color={sparkColor || c} height={20} width={50} />
        )}
      </div>
    </button>
  );
};

// ── Quick action chip ──────────────────────────────────────
const QuickAction = ({ icon, label, color = CDV.text, onClick }) => (
  <button onClick={onClick} style={{
    flex: '0 0 auto', height: 38, padding: '0 14px 0 12px', borderRadius: 99,
    border: `1px solid ${CDV.stroke}`, background: CDV.surface, color: CDV.text,
    fontFamily: 'inherit', display: 'flex', alignItems: 'center', gap: 6,
    fontSize: 13, fontWeight: 500,
  }}>
    <Icon name={icon} size={14} color={color} />
    {label}
  </button>
);

// ── Task inline row ────────────────────────────────────────
const TaskInlineRow = ({ task, onToggle, onClick }) => {
  const catColor = CDV.cats[task.category] || CDV.brand;
  return (
    <div onClick={onClick} style={{
      padding: 14, paddingLeft: 16, borderRadius: 16,
      background: `linear-gradient(135deg, ${catColor}0d 0%, ${CDV.surface} 50%)`,
      border: `1px solid ${catColor}22`,
      display: 'flex', alignItems: 'center', gap: 12,
      position: 'relative', overflow: 'hidden',
      boxShadow: `0 4px 14px -10px ${catColor}40`,
    }}>
      <div style={{
        position: 'absolute', left: 0, top: 14, bottom: 14, width: 3, borderRadius: 99,
        background: `linear-gradient(180deg, ${catColor}, ${catColor}40)`,
        boxShadow: `0 0 10px ${catColor}80`,
      }} />
      <Checkbox checked={task.done} onChange={() => onToggle(task.id)} color={catColor} />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 14, fontWeight: 500, color: task.done ? CDV.textMuted : CDV.text, textDecoration: task.done ? 'line-through' : 'none', lineHeight: 1.3 }}>
          {task.title}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 4 }}>
          <div style={{ fontSize: 11, color: CDV.textDim, display: 'flex', alignItems: 'center', gap: 4 }}>
            <Icon name="clock" size={11} /> {task.time}
          </div>
          {task.priority === 'alta' && <Pill color={CDV.coral} size="sm">Alta</Pill>}
          {task.aiSuggested && <Pill color={CDV.brand} size="sm"><Icon name="sparkle" size={9} /> IA</Pill>}
        </div>
      </div>
    </div>
  );
};

// ── Habit chip ─────────────────────────────────────────────
const HabitChip = ({ habit, onToggle }) => {
  const done = habit.done;
  return (
    <button onClick={() => onToggle(habit.id)} style={{
      flex: '0 0 auto', width: 110, padding: 14, borderRadius: 20,
      background: done ? habit.color + '15' : CDV.surface,
      border: `1px solid ${done ? habit.color + '50' : CDV.stroke}`,
      color: CDV.text, fontFamily: 'inherit', textAlign: 'left',
      display: 'flex', flexDirection: 'column', gap: 8, position: 'relative',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
        <div style={{
          width: 32, height: 32, borderRadius: 10, background: habit.color + '24',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Icon name={habit.icon} size={16} color={habit.color} />
        </div>
        {done && <Icon name="check" size={16} color={habit.color} />}
      </div>
      <div style={{ fontSize: 12, fontWeight: 600, lineHeight: 1.2 }}>{habit.name}</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 11, color: CDV.flame, fontWeight: 600 }}>
        <Icon name="flame" size={11} color={CDV.flame} /> {habit.streak} dias
      </div>
    </button>
  );
};

// ── Goal hero card ─────────────────────────────────────────
const GoalHeroCard = ({ goal, onClick }) => (
  <div onClick={onClick} style={{
    padding: 18, borderRadius: 22, background: CDV.surface,
    border: `1px solid ${CDV.stroke}`, position: 'relative', overflow: 'hidden',
  }}>
    <div style={{
      position: 'absolute', top: -40, right: -40, width: 180, height: 180, borderRadius: 99,
      background: 'radial-gradient(circle, rgba(94,227,168,0.22), transparent 70%)',
      filter: 'blur(20px)',
    }} />
    <div style={{ position: 'relative' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
        <div>
          <div style={{ fontSize: 11, color: CDV.mint, fontWeight: 700, letterSpacing: 0.5, textTransform: 'uppercase' }}>Meta principal</div>
          <div style={{ fontSize: 18, fontWeight: 600, marginTop: 4, color: CDV.text, letterSpacing: -0.2 }}>{goal.title}</div>
        </div>
        <div style={{
          width: 44, height: 44, borderRadius: 12, background: CDV.mintSoft,
          display: 'flex', alignItems: 'center', justifyContent: 'center', color: CDV.mint,
        }}><Icon name="target" size={22} /></div>
      </div>
      <div style={{ marginTop: 16 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 6 }}>
          <div style={{ fontSize: 12, color: CDV.textDim }}>R$ {goal.savedReais.toLocaleString('pt-BR')} / R$ {goal.targetReais.toLocaleString('pt-BR')}</div>
          <div style={{ fontSize: 12, color: CDV.mint, fontWeight: 600 }}>{goal.progress}%</div>
        </div>
        <ProgressBar percent={goal.progress} gradient="linear-gradient(90deg, #5EE3A8, #B197FC)" height={6} />
        <div style={{ fontSize: 11, color: CDV.textMuted, marginTop: 10 }}>Prazo: {goal.deadline} · No ritmo certo</div>
      </div>
    </div>
  </div>
);

Object.assign(window, { DashboardScreen });
