// home.jsx — Home page for Pinnacle Command Centre
// Live weather via Open-Meteo (no key) · Navigable monthly calendar with SA holidays
// Yearly overview · All existing sidebar cards preserved

const { useState: useStateH, useEffect: useEffectH } = React;

const STAGES_HOME = ['Lead','Prospect','Demo','Proposal','Onboarding','Active'];

/* ── SA Public Holidays 2025–2027 ────────────────────────────────── */
const SA_HOLIDAYS = {
  '2025-01-01':"New Year's Day",'2025-03-21':'Human Rights Day',
  '2025-04-18':'Good Friday','2025-04-21':'Family Day',
  '2025-04-27':'Freedom Day','2025-05-01':"Workers' Day",
  '2025-06-16':'Youth Day','2025-08-09':"Women's Day",
  '2025-09-24':'Heritage Day','2025-12-16':'Reconciliation Day',
  '2025-12-25':'Christmas Day','2025-12-26':'Day of Goodwill',

  '2026-01-01':"New Year's Day",'2026-03-21':'Human Rights Day',
  '2026-04-03':'Good Friday','2026-04-06':'Family Day',
  '2026-04-27':'Freedom Day','2026-05-01':"Workers' Day",
  '2026-06-16':'Youth Day','2026-08-09':"Women's Day",
  '2026-09-24':'Heritage Day','2026-12-16':'Reconciliation Day',
  '2026-12-25':'Christmas Day','2026-12-26':'Day of Goodwill',

  '2027-01-01':"New Year's Day",'2027-03-21':'Human Rights Day',
  '2027-03-26':'Good Friday','2027-03-29':'Family Day',
  '2027-04-27':'Freedom Day','2027-05-01':"Workers' Day",
  '2027-06-16':'Youth Day','2027-08-09':"Women's Day",
  '2027-09-24':'Heritage Day','2027-12-16':'Reconciliation Day',
  '2027-12-25':'Christmas Day','2027-12-26':'Day of Goodwill',
};

/* ── Helpers ─────────────────────────────────────────────────────── */
function isoWeek(d) {
  const dt = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
  const day = dt.getUTCDay() || 7;
  dt.setUTCDate(dt.getUTCDate() + 4 - day);
  const ys = new Date(Date.UTC(dt.getUTCFullYear(), 0, 1));
  return Math.ceil((((dt - ys) / 86400000) + 1) / 7);
}
function toKey(d) {
  return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
}

/* ── WMO weather codes ───────────────────────────────────────────── */
const WMO = {
  0:{l:'Clear sky',e:'☀️'},1:{l:'Mainly clear',e:'🌤️'},2:{l:'Partly cloudy',e:'⛅'},
  3:{l:'Overcast',e:'☁️'},45:{l:'Foggy',e:'🌫️'},48:{l:'Icy fog',e:'🌫️'},
  51:{l:'Lt drizzle',e:'🌦️'},53:{l:'Drizzle',e:'🌦️'},55:{l:'Hvy drizzle',e:'🌧️'},
  61:{l:'Lt rain',e:'🌧️'},63:{l:'Rain',e:'🌧️'},65:{l:'Hvy rain',e:'🌧️'},
  80:{l:'Showers',e:'🌦️'},81:{l:'Shower',e:'🌧️'},82:{l:'Hvy shower',e:'⛈️'},
  95:{l:'Thunderstorm',e:'⛈️'},96:{l:'Thunderstorm',e:'⛈️'},99:{l:'Thunderstorm',e:'⛈️'},
};
const wmo  = (c) => WMO[c] || WMO[Math.floor((c||0)/10)*10] || {l:'—',e:'🌡️'};
const wDir = (deg) => ['N','NE','E','SE','S','SW','W','NW'][Math.round(((deg||0)%360)/45)%8];
const DSHRT = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];

/* ── WeatherCard ─────────────────────────────────────────────────── */
function WeatherCard() {
  const [wx,  setWx]  = useStateH(null);
  const [err, setErr] = useStateH(false);
  const [now, setNow] = useStateH(() => new Date());

  useEffectH(() => {
    const tick = setInterval(() => setNow(new Date()), 60000);
    fetch(
      'https://api.open-meteo.com/v1/forecast' +
      '?latitude=-29.1210&longitude=26.2141' +
      '&current=temperature_2m,weathercode,windspeed_10m,winddirection_10m' +
      '&daily=temperature_2m_max,temperature_2m_min,weathercode,precipitation_probability_max' +
      '&timezone=Africa%2FJohannesburg&forecast_days=5'
    ).then(r => r.json()).then(setWx).catch(() => setErr(true));
    return () => clearInterval(tick);
  }, []);

  return (
    <Card sub="WEATHER" title="Bloemfontein">
      {!wx && !err && (
        <div style={{ padding:'18px 0', color:'var(--muted)', fontSize:12, fontStyle:'italic', textAlign:'center' }}>
          Loading weather…
        </div>
      )}
      {err && (
        <div style={{ padding:'18px 0', color:'var(--muted)', fontSize:12, fontStyle:'italic', textAlign:'center' }}>
          Weather unavailable — check network connection
        </div>
      )}
      {wx && (() => {
        const cur = wx.current;
        const day = wx.daily;
        const cond = wmo(cur.weathercode);
        return (
          <>
            <div style={{ display:'flex', alignItems:'flex-end', gap:14, marginTop:8 }}>
              <div style={{
                fontFamily:"'Cormorant Garamond',serif", fontStyle:'italic',
                fontSize:72, lineHeight:1,
                background:'var(--gold-gradient-text)',
                WebkitBackgroundClip:'text', backgroundClip:'text', color:'transparent'
              }}>
                {Math.round(cur.temperature_2m)}°
              </div>
              <div style={{ paddingBottom:6 }}>
                <div style={{ fontSize:26, lineHeight:1 }}>{cond.e}</div>
                <div style={{ fontSize:13, color:'var(--ink-3)', fontWeight:600, marginTop:3 }}>{cond.l}</div>
                <div style={{ fontSize:12, color:'var(--muted)', marginTop:2 }}>
                  Wind {Math.round(cur.windspeed_10m)} km/h {wDir(cur.winddirection_10m)}
                </div>
                <div style={{ fontSize:12, color:'var(--muted)' }}>
                  Hi {Math.round(day.temperature_2m_max[0])}° · Lo {Math.round(day.temperature_2m_min[0])}°
                </div>
              </div>
            </div>
            {/* 4-day forecast strip */}
            <div style={{ display:'grid', gridTemplateColumns:'repeat(4,1fr)', gap:4,
                          marginTop:12, paddingTop:10, borderTop:'1px solid var(--line)' }}>
              {[1,2,3,4].map(i => {
                const fd   = new Date(day.time[i]);
                const fcnd = wmo(day.weathercode[i]);
                const rain = day.precipitation_probability_max[i];
                return (
                  <div key={i} style={{ textAlign:'center', padding:'6px 2px',
                    background:'var(--glass-1)', borderRadius:8 }}>
                    <div style={{ fontSize:10, fontWeight:700, color:'var(--muted)', letterSpacing:'0.06em' }}>
                      {DSHRT[fd.getDay()]}
                    </div>
                    <div style={{ fontSize:20, margin:'3px 0' }}>{fcnd.e}</div>
                    {rain > 20 && (
                      <div style={{ fontSize:9, color:'var(--sapphire)', fontWeight:700 }}>
                        {rain}%💧
                      </div>
                    )}
                    <div style={{ fontSize:12, fontWeight:700, color:'var(--ink-2)' }}>
                      {Math.round(day.temperature_2m_max[i])}°
                    </div>
                    <div style={{ fontSize:10, color:'var(--muted-2)' }}>
                      {Math.round(day.temperature_2m_min[i])}°
                    </div>
                  </div>
                );
              })}
            </div>
          </>
        );
      })()}
      <div style={{ marginTop:10, paddingTop:10, borderTop:'1px solid var(--line)',
                    fontSize:12, color:'var(--muted)' }}>
        {now.toLocaleDateString('en-ZA',{weekday:'long',day:'numeric',month:'long',year:'numeric'})}
      </div>
    </Card>
  );
}

/* ── HomeDayModal — full-day hourly view popup (click a calendar day) ── */
const HOME_DAY_HOURS = ['07:00','08:00','09:00','10:00','11:00','12:00','13:00','14:00','15:00','16:00','17:00','18:00'];
const HOME_CAT_COLOR = { meeting:'var(--sapphire)', deadline:'var(--ruby-400)', call:'var(--gold-500)', task:'var(--gold-400)', admin:'var(--ink-3)', personal:'var(--muted)' };
const HOME_DIARY_CATS = ['task','meeting','call','deadline','admin','personal'];
function HomeDayModal({ date, onClose, onChanged }) {
  const ymd = toKey(date);
  const dateLabel = date.toLocaleDateString('en-ZA',{ weekday:'long', day:'numeric', month:'long', year:'numeric' });
  const [entries, setEntries] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [adding, setAdding]   = React.useState(false);
  const [editId, setEditId]   = React.useState(null);
  const [saving, setSaving]   = React.useState(false);
  const [f, setF] = React.useState({ title:'', start_time:'09:00', end_time:'10:00', category:'task' });

  const fetchDay = React.useCallback(() => {
    if (!window.pccDb) { setLoading(false); return; }
    window.pccDb.diary.list(`entry_date=eq.${ymd}`)
      .then(rows => { (rows||[]).sort((a,b)=>((a.start_time||'99:99') < (b.start_time||'99:99') ? -1 : 1)); setEntries(rows||[]); })
      .catch(()=>{}).finally(()=>setLoading(false));
  }, [ymd]);
  React.useEffect(() => { fetchDay(); }, [fetchDay]);

  const hourOf = (t) => t ? parseInt(String(t).slice(0,2),10) : null;
  const lbl = { display:'block', fontSize:10, fontWeight:700, letterSpacing:'0.1em', textTransform:'uppercase', color:'var(--muted)', marginBottom:4 };

  function openAddAt(hour) {
    const sh = String(hour).padStart(2,'0'), eh = String(Math.min(hour+1,23)).padStart(2,'0');
    setEditId(null);
    setF({ title:'', start_time:sh+':00', end_time:eh+':00', category:'task' });
    setAdding(true);
  }
  function openEditEntry(ev, e) {
    if (e) e.stopPropagation();
    setEditId(ev.id);
    setF({ title:ev.title||'', start_time:hhmmH(ev.start_time)||'', end_time:hhmmH(ev.end_time)||'', category:ev.category||'task' });
    setAdding(true);
  }
  async function saveEntry() {
    if (!f.title.trim()) { alert('Give the entry a title first.'); return; }
    setSaving(true);
    try {
      const payload = { entry_date:ymd, start_time:f.start_time||null, end_time:f.end_time||null, title:f.title.trim(), category:f.category };
      if (editId) {
        await window.pccDb.diary.update(editId, payload);
      } else {
        await window.pccDb.diary.create({ ...payload, completed:false });
        window.pccDb.logActivity('system.diary_created', f.title.trim(), date.toLocaleDateString('en-ZA',{day:'numeric',month:'short'}));
      }
      setAdding(false); setEditId(null); fetchDay(); if (onChanged) onChanged();
    } catch (e) { alert('Save failed: ' + e.message); }
    finally { setSaving(false); }
  }
  async function toggleDone(ev, e) {
    e.stopPropagation();
    try { await window.pccDb.diary.update(ev.id, { completed: !ev.completed }); fetchDay(); if (onChanged) onChanged(); }
    catch (err) { alert('Update failed: ' + err.message); }
  }
  async function deleteEntry(ev, e) {
    if (e) e.stopPropagation();
    if (!window.confirm(`Delete "${ev.title}"?`)) return;
    try {
      await window.pccDb.diary.remove(ev.id);
      window.pccDb.logActivity('system.diary_deleted', ev.title);
      fetchDay(); if (onChanged) onChanged();
    } catch (err) { alert('Delete failed: ' + err.message); }
  }

  const chip = (ev) => (
    <div key={ev.id} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:8,
      borderRadius:6, padding:'5px 9px', marginBottom:4, background:'var(--glass-2)',
      borderLeft:'3px solid ' + (HOME_CAT_COLOR[ev.category] || 'var(--gold-400)'), opacity: ev.completed ? 0.55 : 1 }}>
      <div style={{ minWidth:0 }}>
        <div style={{ fontSize:12, fontWeight:600, color:'var(--ink)', textDecoration: ev.completed ? 'line-through' : 'none' }}>{ev.title}</div>
        {(ev.start_time || ev.end_time) && (
          <div style={{ fontSize:10, color:'var(--muted)' }}>{hhmmH(ev.start_time)}{ev.end_time ? '–' + hhmmH(ev.end_time) : ''}{ev.category ? ' · ' + ev.category : ''}</div>
        )}
      </div>
      <div style={{ display:'flex', gap:5, flexShrink:0, alignItems:'center' }}>
        <button title={ev.completed ? 'Mark not done' : 'Mark done'} onClick={(e)=>toggleDone(ev,e)}
          style={{ width:20, height:20, borderRadius:4, cursor:'pointer', border:'1.5px solid var(--line-strong)',
            background: ev.completed ? 'var(--gold-400)' : 'transparent', color: ev.completed ? 'var(--gold-700)' : 'transparent', fontSize:11, lineHeight:'16px' }}>✓</button>
        <button title="Edit" onClick={(e)=>openEditEntry(ev,e)}
          style={{ width:20, height:20, borderRadius:4, cursor:'pointer', border:'1.5px solid var(--line-strong)', background:'transparent', color:'var(--gold-400)', fontSize:11, lineHeight:'16px' }}>✎</button>
        <button title="Delete" onClick={(e)=>deleteEntry(ev,e)}
          style={{ width:20, height:20, borderRadius:4, cursor:'pointer', border:'1.5px solid var(--ruby-400)', background:'transparent', color:'var(--ruby-400)', fontSize:11, lineHeight:'16px' }}>✕</button>
      </div>
    </div>
  );

  const untimed = entries.filter(e => !e.start_time);

  return (
    <div className="modal-overlay" onClick={e => e.target===e.currentTarget && onClose()}>
      <div className="modal" style={{ maxWidth:560, maxHeight:'85vh', overflowY:'auto' }}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline', marginBottom:10 }}>
          <div className="modal-title" style={{ marginBottom:0 }}>{dateLabel}</div>
          <button className="btn-primary" style={{ fontSize:11, padding:'4px 12px' }} onClick={() => openAddAt(9)}>+ New Entry</button>
        </div>

        {adding && (
          <div style={{ border:'1.5px solid var(--gold-400)', borderRadius:8, padding:12, marginBottom:12, background:'var(--glass-1)' }}>
            <input className="input" autoFocus placeholder="What's happening?" value={f.title}
              onChange={e=>setF(s=>({...s,title:e.target.value}))} onKeyDown={e=>e.key==='Enter'&&saveEntry()} style={{ marginBottom:8 }} />
            <div style={{ display:'flex', gap:8, marginBottom:8 }}>
              <div style={{ flex:1 }}><label style={lbl}>Start</label><input className="input" type="time" value={f.start_time} onChange={e=>setF(s=>({...s,start_time:e.target.value}))} /></div>
              <div style={{ flex:1 }}><label style={lbl}>End</label><input className="input" type="time" value={f.end_time} onChange={e=>setF(s=>({...s,end_time:e.target.value}))} /></div>
              <div style={{ flex:1 }}><label style={lbl}>Type</label><select className="input" value={f.category} onChange={e=>setF(s=>({...s,category:e.target.value}))}>{HOME_DIARY_CATS.map(c=><option key={c} value={c}>{c.charAt(0).toUpperCase()+c.slice(1)}</option>)}</select></div>
            </div>
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', gap:8 }}>
              <div>{editId && <button className="btn-ghost" style={{ color:'var(--ruby-400)', borderColor:'var(--ruby-400)' }} disabled={saving}
                onClick={() => { const cur = entries.find(x => x.id === editId); setAdding(false); if (cur) deleteEntry(cur); }}>Delete</button>}</div>
              <div style={{ display:'flex', gap:8 }}>
                <button className="btn-ghost" disabled={saving} onClick={()=>{ setAdding(false); setEditId(null); }}>Cancel</button>
                <button className="btn-primary" disabled={saving} onClick={saveEntry}>{saving ? 'Saving…' : (editId ? 'Save changes' : 'Add entry')}</button>
              </div>
            </div>
          </div>
        )}

        {loading ? (
          <div style={{ padding:'20px 0', textAlign:'center', color:'var(--muted)', fontSize:12 }}>Loading…</div>
        ) : (
          <>
            {entries.length === 0 && !adding && (
              <div style={{ fontSize:12, color:'var(--muted)', fontStyle:'italic', padding:'4px 0 10px' }}>
                Nothing scheduled this day. Click <strong>+ New Entry</strong> or any hour below to add one.
              </div>
            )}
            {HOME_DAY_HOURS.map(h => {
              const hr = parseInt(h.slice(0,2),10);
              const slot = entries.filter(e => hourOf(e.start_time) === hr);
              return (
                <div key={h} style={{ display:'flex', gap:10, borderTop:'1px solid var(--line-cool)', minHeight:38, padding:'5px 0' }}>
                  <div style={{ width:46, flexShrink:0, fontSize:11, fontWeight:700, color:'var(--muted)', paddingTop:3 }}>{h}</div>
                  <div style={{ flex:1, cursor: slot.length ? 'default' : 'pointer' }}
                    onClick={() => { if (!slot.length) openAddAt(hr); }}>
                    {slot.length === 0 ? <div style={{ fontSize:11, color:'var(--muted-2)', paddingTop:3 }}>+</div> : slot.map(chip)}
                  </div>
                </div>
              );
            })}
            {untimed.length > 0 && (
              <div style={{ marginTop:12 }}>
                <div style={{ fontSize:10, fontWeight:700, letterSpacing:'0.14em', textTransform:'uppercase', color:'var(--muted)', marginBottom:6 }}>No time set</div>
                {untimed.map(chip)}
              </div>
            )}
          </>
        )}
        <div style={{ marginTop:14, textAlign:'right' }}>
          <button className="btn-ghost" onClick={onClose}>Close</button>
        </div>
      </div>
    </div>
  );
}

/* ── CalendarCard (monthly, navigable, SA holidays) ──────────────── */
function CalendarCard() {
  const real = new Date();
  const [vy, setVy] = useStateH(real.getFullYear());
  const [vm, setVm] = useStateH(real.getMonth());

  function prev()    { if (vm===0){ setVy(y=>y-1); setVm(11); } else setVm(m=>m-1); }
  function next()    { if (vm===11){ setVy(y=>y+1); setVm(0); } else setVm(m=>m+1); }
  function goToday() { setVy(real.getFullYear()); setVm(real.getMonth()); }

  // Live diary entries → calendar dots, grouped by entry_date.
  const [eventsByDate, setEventsByDate] = useStateH({});
  const [dayModal, setDayModal] = useStateH(null); // Date or null — full-day popup
  const fetchEvents = React.useCallback(() => {
    if (!window.pccDb) return;
    window.pccDb.diary.list().then(rows => {
      const map = {};
      (rows || []).forEach(e => { (map[e.entry_date] = map[e.entry_date] || []).push(e); });
      setEventsByDate(map);
    }).catch(() => {});
  }, []);
  useEffectH(() => { fetchEvents(); }, [fetchEvents]);

  // Bridge so the Yearly Overview can drive THIS calendar (the "command centre").
  const rootRef = React.useRef(null);
  useEffectH(() => {
    window.__pccGotoMonth = (y, m) => {
      setVy(y); setVm(m);
      if (rootRef.current) rootRef.current.scrollIntoView({ behavior:'smooth', block:'start' });
    };
    window.__pccOpenDay = (date) => setDayModal(date);
  }, []);
  const CAL_COLOR = { meeting:'sapphire', deadline:'ruby', call:'gold', task:'gold', admin:'gold', personal:'sapphire' };

  const first      = new Date(vy, vm, 1);
  const dimMonth   = new Date(vy, vm+1, 0).getDate();
  const startDay   = (first.getDay()+6)%7;  // Mon=0
  const monthLabel = first.toLocaleDateString('en-ZA',{month:'long',year:'numeric'});
  const WDAYS      = ['MON','TUE','WED','THU','FRI','SAT','SUN'];
  const todayKey   = toKey(real);

  // Build cell array (null = padding, Date = real day)
  const cells = [];
  for (let i=0; i<startDay; i++) cells.push(null);
  for (let d=1; d<=dimMonth; d++) cells.push(new Date(vy, vm, d));
  const rem = (7 - cells.length%7)%7;
  for (let i=0; i<rem; i++) cells.push(null);
  const weeks = [];
  for (let i=0; i<cells.length; i+=7) weeks.push(cells.slice(i,i+7));

  return (
    <div ref={rootRef}>
    <Card sub="CALENDAR" title={monthLabel}
      action={
        <div style={{ display:'flex', gap:4, alignItems:'center' }}>
          <button className="btn-ghost" onClick={prev}
            style={{ padding:'3px 10px', fontSize:16, lineHeight:1 }}>‹</button>
          <button className="btn-ghost" onClick={goToday}
            style={{ padding:'3px 10px', fontSize:11 }}>Today</button>
          <button className="btn-ghost" onClick={next}
            style={{ padding:'3px 10px', fontSize:16, lineHeight:1 }}>›</button>
        </div>
      }>
      {/* Day headers */}
      <div className="mcal-grid" style={{ marginTop:10 }}>
        <div />
        {WDAYS.map(d => <div key={d} className="mcal-header">{d}</div>)}
      </div>
      {/* Weeks */}
      {weeks.map((week, wi) => {
        const anchor = week.find(Boolean);
        const wn     = anchor ? isoWeek(anchor) : '—';
        return (
          <div key={wi} className="mcal-grid">
            <div className="mcal-wk">W{wn}</div>
            {week.map((cell, ci) => {
              if (!cell) return <div key={ci} className="mcal-cell" />;
              const dk      = toKey(cell);
              const holiday = SA_HOLIDAYS[dk];
              const evts    = eventsByDate[dk] || [];
              const isToday = dk === todayKey;
              const isSun   = ci===6;
              const isSat   = ci===5;
              return (
                <div key={ci} className={`mcal-cell${isToday?' mcal-cell-today':''}`}
                  onClick={() => setDayModal(cell)} style={{ cursor:'pointer' }}
                  title="Open full day">
                  <div className={`mcal-day-num${isToday?' mcal-day-today':isSun?' mcal-day-sun':isSat?' mcal-day-sat':''}`}>
                    {cell.getDate()}
                  </div>
                  {holiday && <div className="mcal-holiday" title={holiday}>{holiday}</div>}
                  {evts.slice(0,2).map((ev) => (
                    <div key={ev.id} className={`cal-event cal-event-${CAL_COLOR[ev.category] || 'gold'}`} style={{fontSize:9}}
                      title={ev.title}>
                      {ev.title}
                    </div>
                  ))}
                  {evts.length > 2 && (
                    <div style={{ fontSize:8, color:'var(--muted)', paddingLeft:2 }}>+{evts.length - 2} more</div>
                  )}
                </div>
              );
            })}
          </div>
        );
      })}
    </Card>
    {dayModal && (
      <HomeDayModal date={dayModal} onClose={() => setDayModal(null)} onChanged={fetchEvents} />
    )}
    </div>
  );
}

/* ── YearlyCalendarCard ──────────────────────────────────────────── */
function YearlyCalendarCard() {
  const real = new Date();
  const [vy, setVy] = useStateH(real.getFullYear());
  const WDAYS = ['M','T','W','T','F','S','S'];
  const todayKey = toKey(real);

  return (
    <Card sub="YEARLY OVERVIEW" title={String(vy)}
      action={
        <div style={{ display:'flex', gap:4, alignItems:'center' }}>
          <button className="btn-ghost" onClick={() => setVy(y=>y-1)}
            style={{ padding:'3px 10px', fontSize:16, lineHeight:1 }}>‹</button>
          <button className="btn-ghost" onClick={() => setVy(real.getFullYear())}
            style={{ padding:'3px 10px', fontSize:11 }}>This year</button>
          <button className="btn-ghost" onClick={() => setVy(y=>y+1)}
            style={{ padding:'3px 10px', fontSize:16, lineHeight:1 }}>›</button>
        </div>
      }>
      <div className="ycal-grid">
        {Array.from({length:12},(_,mi) => {
          const first     = new Date(vy, mi, 1);
          const dim       = new Date(vy, mi+1, 0).getDate();
          const startDay  = (first.getDay()+6)%7;
          const monthName = first.toLocaleDateString('en-ZA',{month:'long'});

          const cells = [];
          for (let i=0; i<startDay; i++) cells.push(null);
          for (let d=1; d<=dim; d++) cells.push(d);
          const rem = (7-cells.length%7)%7;
          for (let i=0; i<rem; i++) cells.push(null);

          return (
            <div key={mi} className="ycal-month">
              <div className="ycal-month-name" title="Open this month in the calendar"
                onClick={() => window.__pccGotoMonth && window.__pccGotoMonth(vy, mi)}>{monthName}</div>
              <div className="ycal-mini">
                {WDAYS.map((d,i) => <div key={i} className="ycal-dow">{d}</div>)}
                {cells.map((day, ci) => {
                  if (!day) return <div key={ci} />;
                  const dk      = `${vy}-${String(mi+1).padStart(2,'0')}-${String(day).padStart(2,'0')}`;
                  const isHol   = !!SA_HOLIDAYS[dk];
                  const isTod   = dk === todayKey;
                  const isSun   = ci%7===6;
                  const isSat   = ci%7===5;
                  return (
                    <div key={ci} title="Open this day"
                      onClick={() => window.__pccOpenDay && window.__pccOpenDay(new Date(vy, mi, day))}
                      className={
                      `ycal-day${isTod?' ycal-day-today':isHol?' ycal-day-holiday':isSun?' ycal-day-sun':isSat?' ycal-day-sat':''}`
                    }>{day}</div>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
    </Card>
  );
}

/* ── PipelineCard ────────────────────────────────────────────────── */
function PipelineCard() {
  const [clients, setClients] = React.useState([]);
  React.useEffect(() => {
    if (!window.pccDb) return;
    window.pccDb.clients.list().then(rows => setClients(rows || [])).catch(() => {});
  }, []);
  return (
    <Card sub="SALES" title="Pipeline snapshot"
      action={<button className="btn-ghost" style={{ fontSize:11, padding:'4px 12px' }}>Open Clients ▾</button>}>
      <div className="pipeline" style={{ marginTop:8 }}>
        {STAGES_HOME.map(stage => {
          const items = clients.filter(c => (c.pipeline_stage || 'Lead') === stage);
          return (
            <div key={stage} className="kanban-col">
              <div className="kanban-col-head">
                <span>{stage}</span>
                <span className="kanban-count">{items.length}</span>
              </div>
              {items.map(c => (
                <div key={c.id} className="kanban-card">
                  <div className="kanban-name">{c.business_name}</div>
                  <div className="kanban-meta">
                    {c.plan && <span>{c.plan}</span>}
                    {Number(c.monthly_value) > 0 && <span className="kanban-val"> · R {Number(c.monthly_value).toLocaleString('en-ZA')}</span>}
                  </div>
                </div>
              ))}
            </div>
          );
        })}
      </div>
    </Card>
  );
}

/* ── YouTubeCard ─────────────────────────────────────────────────── */
function YouTubeCard() {
  const [url, setUrl] = React.useState(() => localStorage.getItem('pcc-yt-url') || '');
  const videoId = window.parseYouTubeId ? window.parseYouTubeId(url) : null;

  function handleGo()   { if (window.__ytPlay) window.__ytPlay(url); }
  function handleClear(){ setUrl(''); if (window.__ytClear) window.__ytClear(); }
  function handleKey(e) { if (e.key==='Enter') handleGo(); }

  return (
    <Card sub="MEDIA PLAYER" title="YouTube">
      <div style={{ marginTop:8 }}>
        {videoId ? (
          <div>
            <img src={`https://img.youtube.com/vi/${videoId}/mqdefault.jpg`}
              style={{ width:'100%', borderRadius:6, border:'1.5px solid var(--gold-400)', display:'block' }}
              alt="Now playing" />
            <div style={{ display:'flex', alignItems:'center', gap:6, marginTop:6 }}>
              <div style={{ width:7, height:7, borderRadius:'50%', background:'var(--positive)', flexShrink:0 }} />
              <span style={{ fontSize:11, color:'var(--muted)' }}>Playing — controls in bottom bar</span>
            </div>
          </div>
        ) : (
          <div style={{ display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center',
            padding:'18px 0', gap:6, color:'var(--muted)' }}>
            <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
              <polygon points="5 3 19 12 5 21 5 3" />
            </svg>
            <span style={{ fontSize:11 }}>Paste a URL below to play</span>
          </div>
        )}
        <div style={{ marginTop:8, display:'flex', gap:6 }}>
          <input className="input" value={url} onChange={e => setUrl(e.target.value)} onKeyDown={handleKey}
            placeholder="Paste YouTube URL…" style={{ flex:1, fontSize:12, padding:'7px 10px' }} />
          <button className="btn-ghost" onClick={handleGo} style={{ padding:'6px 10px', fontSize:12 }}>▶</button>
          {videoId && (
            <button className="btn-ghost" onClick={handleClear} style={{ padding:'6px 10px', fontSize:12 }}>■</button>
          )}
        </div>
      </div>
    </Card>
  );
}

/* ── ScheduledCard — live from diary_entries (today) ─────────────── */
function hhmmH(t) { return t ? String(t).slice(0,5) : ''; }
function durationMinsH(s, e) {
  if (!s || !e) return null;
  const a = s.split(':').map(Number), b = e.split(':').map(Number);
  const mins = (b[0]*60 + (b[1]||0)) - (a[0]*60 + (a[1]||0));
  return mins > 0 ? mins : null;
}
function ScheduledCard() {
  const now = new Date();
  const todayKey = toKey(now);
  const dateStr = now.toLocaleDateString('en-ZA',{weekday:'long',day:'numeric',month:'long'});
  const [events, setEvents]   = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    if (!window.pccDb) { setLoading(false); return; }
    window.pccDb.diary.list(`entry_date=eq.${todayKey}`)
      .then(rows => {
        (rows || []).sort((a,b) => ((a.start_time||'99:99') < (b.start_time||'99:99') ? -1 : 1));
        setEvents(rows || []);
      })
      .catch(() => {})
      .finally(() => setLoading(false));
  }, [todayKey]);

  return (
    <Card sub="SCHEDULED" title={`Today — ${dateStr}`}
      action={<button className="btn-primary" style={{ fontSize:10, padding:'4px 12px' }}
        onClick={() => window.__nav && window.__nav('diary')}>+ New Entry</button>}>
      <div style={{ display:'flex', flexDirection:'column', gap:0, marginTop:8 }}>
        {loading && (
          <div style={{ textAlign:'center', padding:'16px 0', color:'var(--muted)', fontSize:12, fontStyle:'italic' }}>Loading…</div>
        )}
        {!loading && events.length === 0 && (
          <div style={{ textAlign:'center', padding:'16px 0', color:'var(--muted)', fontSize:12, fontStyle:'italic' }}>
            No events scheduled today.<br />Click + New Entry to add one.
          </div>
        )}
        {events.map((ev) => {
          const mins = durationMinsH(hhmmH(ev.start_time), hhmmH(ev.end_time));
          return (
            <div key={ev.id} style={{ display:'flex', gap:12, alignItems:'flex-start',
              padding:'8px 0', borderBottom:'1px solid var(--line-cool)', opacity: ev.completed ? 0.55 : 1 }}>
              <div style={{ minWidth:42, fontWeight:700, fontSize:12, color:'var(--gold-500)' }}>{hhmmH(ev.start_time) || '—'}</div>
              <div>
                <div style={{ fontSize:13, color:'var(--ink-2)', fontWeight:600, textDecoration: ev.completed ? 'line-through' : 'none' }}>{ev.title}</div>
                <div style={{ fontSize:11, color:'var(--muted)' }}>{mins != null ? mins + ' min' : (ev.category || '')}</div>
              </div>
            </div>
          );
        })}
      </div>
    </Card>
  );
}

/* ── NotesCard ───────────────────────────────────────────────────── */
function NotesCard() {
  const [note, setNote] = useStateH(() => localStorage.getItem('pcc-quicknote') || '');
  function save(val) {
    setNote(val);
    localStorage.setItem('pcc-quicknote', val);
  }
  return (
    <Card sub="NOTES" title="Quick Note">
      <textarea value={note} onChange={e => save(e.target.value)}
        placeholder="Capture a thought…"
        style={{ width:'100%', minHeight:72, marginTop:8,
          background:'transparent', border:'none', outline:'none',
          resize:'vertical', fontSize:14,
          fontFamily:"'Cormorant Garamond',serif", fontStyle:'italic',
          color:'var(--ink-2)', lineHeight:1.6 }} />
    </Card>
  );
}

/* ── ActivityCard — live from activity_feed table ────────────────── */
const ACT_DOT = { lead:'sapphire', demo:'sapphire', provisioning:'sapphire', invoice:'ruby', client:'gold', system:'gold' };
function relTimeH(ts) {
  if (!ts) return '';
  const diff = Math.max(0, Date.now() - new Date(ts).getTime());
  const m = Math.floor(diff / 60000);
  if (m < 1) return 'now';
  if (m < 60) return m + 'm';
  const h = Math.floor(m / 60);
  if (h < 24) return h + 'h';
  const d = Math.floor(h / 24);
  if (d < 7) return d + 'd';
  return new Date(ts).toLocaleDateString('en-ZA', { day:'numeric', month:'short' });
}
function ActivityCard() {
  const [items, setItems]     = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  React.useEffect(() => {
    if (!window.pccDb) { setLoading(false); return; }
    window.pccDb.activity.list()
      .then(rows => setItems((rows || []).slice(0, 14)))
      .catch(() => {})
      .finally(() => setLoading(false));
  }, []);
  return (
    <Card sub="LIVE" title="Activity">
      <div className="activity-list" style={{ marginTop:8 }}>
        {loading && (
          <div style={{ padding:'16px 0', color:'var(--muted)', fontSize:12, fontStyle:'italic', textAlign:'center' }}>Loading…</div>
        )}
        {!loading && items.length === 0 && (
          <div style={{ padding:'16px 0', color:'var(--muted)', fontSize:12, fontStyle:'italic', textAlign:'center' }}>
            Activity feed is empty — actions log here automatically.
          </div>
        )}
        {items.map((a) => (
          <div key={a.id} className="activity-item">
            <div className={`activity-dot activity-dot-${ACT_DOT[a.type] || 'gold'}`} />
            <div className="activity-body">{a.description}</div>
            <div className="activity-time">{relTimeH(a.created_at)}</div>
          </div>
        ))}
      </div>
    </Card>
  );
}

/* ── InboxCard — quick links to Gmail labels + new-mail nudge ────── */
const MAIL_BASE = 'https://mail.google.com/mail/u/info@pinnaclepa.biz/';
const MAIL_LINKS = [
  { label:'Inbox',    url: MAIL_BASE + '#inbox' },
  { label:'Support',  url: MAIL_BASE + '#label/Support' },
  { label:'Disputes', url: MAIL_BASE + '#label/Disputes' },
  { label:'Legal',    url: MAIL_BASE + '#label/Legal' },
  { label:'Info',     url: MAIL_BASE + '#label/info' },
];
function InboxCard() {
  // Honest "check your mail" nudge — a static PWA can't read Gmail unread without OAuth.
  // Flickers if mail hasn't been opened from here in 4h; clears when a link is clicked.
  const [needsCheck, setNeedsCheck] = useStateH(() => {
    const t = +(localStorage.getItem('pcc-mail-checked-at') || 0);
    return (Date.now() - t) > 4 * 3600 * 1000;
  });
  function markChecked() {
    localStorage.setItem('pcc-mail-checked-at', String(Date.now()));
    setNeedsCheck(false);
  }
  return (
    <Card sub="INBOX" title="Pinnacle Mail"
      action={needsCheck
        ? <span title="You haven't checked mail recently" style={{ display:'flex', alignItems:'center', gap:6, fontSize:10, fontWeight:700, color:'var(--ruby-400)' }}><span className="flicker-dot" /> CHECK</span>
        : <span style={{ fontSize:10, color:'var(--positive)' }}>✓ checked</span>}>
      <div style={{ marginTop:8 }}>
        {MAIL_LINKS.map(m => (
          <a key={m.label} className="inbox-link" href={m.url} target="_blank" rel="noopener" onClick={markChecked}>
            <span>{m.label}</span><span className="chev">open ↗</span>
          </a>
        ))}
      </div>
      <div style={{ fontSize:10, color:'var(--muted)', marginTop:4 }}>info@pinnaclepa.biz · opens Gmail</div>
    </Card>
  );
}

/* ── TodoCard — priority to-do list (live, todos table) ──────────── */
const TODO_PRIORITY = ['high','medium','low'];
const TODO_PRIO_COLOR = { high:'var(--ruby-400)', medium:'var(--gold-400)', low:'var(--sapphire)' };
const TODO_PRIO_RANK = { high:0, medium:1, low:2 };
function TodoCard() {
  const [todos, setTodos]   = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [title, setTitle]   = React.useState('');
  const [prio, setPrio]     = React.useState('medium');

  const fetchTodos = React.useCallback(() => {
    if (!window.pccDb) { setLoading(false); return; }
    window.pccDb.todos.list().then(r => setTodos(r || [])).catch(() => {}).finally(() => setLoading(false));
  }, []);
  React.useEffect(() => { fetchTodos(); }, [fetchTodos]);

  const sorted = [...todos].sort((a,b) => {
    if (!!a.done !== !!b.done) return a.done ? 1 : -1;
    const pr = (TODO_PRIO_RANK[a.priority] ?? 1) - (TODO_PRIO_RANK[b.priority] ?? 1);
    if (pr) return pr;
    return (a.due_date || '9999') < (b.due_date || '9999') ? -1 : 1;
  });
  const openCount = todos.filter(t => !t.done).length;

  async function add() {
    if (!title.trim()) return;
    try { await window.pccDb.todos.create({ title:title.trim(), priority:prio, done:false }); setTitle(''); setPrio('medium'); fetchTodos(); }
    catch (e) { alert('Add failed: ' + e.message); }
  }
  async function toggle(t) {
    try { await window.pccDb.todos.update(t.id, { done: !t.done }); setTodos(prev => prev.map(x => x.id === t.id ? { ...x, done: !t.done } : x)); }
    catch (e) { alert('Update failed: ' + e.message); }
  }
  async function del(t) {
    try { await window.pccDb.todos.remove(t.id); setTodos(prev => prev.filter(x => x.id !== t.id)); }
    catch (e) { alert('Delete failed: ' + e.message); }
  }

  return (
    <Card sub="PRIORITY" title="To-Do"
      action={<span style={{ fontSize:11, color:'var(--muted)' }}>{openCount} open</span>}>
      <div style={{ display:'flex', gap:6, marginTop:8 }}>
        <input className="input" value={title} onChange={e => setTitle(e.target.value)} onKeyDown={e => e.key==='Enter' && add()}
          placeholder="Add a task…" style={{ flex:1, fontSize:12, padding:'7px 10px' }} />
        <select className="input" value={prio} onChange={e => setPrio(e.target.value)} style={{ width:90, fontSize:11, padding:'7px 6px' }}>
          {TODO_PRIORITY.map(p => <option key={p} value={p}>{p.charAt(0).toUpperCase()+p.slice(1)}</option>)}
        </select>
        <button className="btn-ghost" onClick={add} style={{ padding:'6px 12px', fontSize:15 }}>+</button>
      </div>
      <div style={{ marginTop:8 }}>
        {loading && <div style={{ padding:'12px 0', color:'var(--muted)', fontSize:12, fontStyle:'italic', textAlign:'center' }}>Loading…</div>}
        {!loading && sorted.length === 0 && (
          <div style={{ padding:'14px 0', color:'var(--muted)', fontSize:12, fontStyle:'italic', textAlign:'center' }}>No tasks yet — add one above.</div>
        )}
        {sorted.map(t => (
          <div key={t.id} style={{ display:'flex', alignItems:'center', gap:8, padding:'6px 0', borderBottom:'1px solid var(--line-cool)', opacity: t.done ? 0.5 : 1 }}>
            <button title={t.done ? 'Mark not done' : 'Mark done'} onClick={() => toggle(t)}
              style={{ flexShrink:0, width:18, height:18, borderRadius:4, cursor:'pointer', border:'1.5px solid ' + (t.done ? 'var(--gold-400)' : TODO_PRIO_COLOR[t.priority] || 'var(--line-strong)'),
                background: t.done ? 'var(--gold-400)' : 'transparent', color: t.done ? 'var(--gold-700)' : 'transparent', fontSize:11, lineHeight:'14px' }}>✓</button>
            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ fontSize:12.5, color:'var(--ink-2)', fontWeight:600, textDecoration: t.done ? 'line-through' : 'none', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{t.title}</div>
            </div>
            <span style={{ flexShrink:0, fontSize:9, fontWeight:700, letterSpacing:'0.06em', textTransform:'uppercase', color: TODO_PRIO_COLOR[t.priority] || 'var(--muted)' }}>{t.priority}</span>
            <button title="Delete" onClick={() => del(t)}
              style={{ flexShrink:0, width:18, height:18, borderRadius:4, cursor:'pointer', border:'1.5px solid var(--ruby-400)', background:'transparent', color:'var(--ruby-400)', fontSize:11, lineHeight:'14px' }}>✕</button>
          </div>
        ))}
      </div>
    </Card>
  );
}

/* ── HomePage ────────────────────────────────────────────────────── */
function HomePage() {
  const fmt = () => {
    const d = new Date();
    const h = d.getHours().toString().padStart(2,'0');
    const m = d.getMinutes().toString().padStart(2,'0');
    const s = d.getSeconds().toString().padStart(2,'0');
    return { hm:`${h}:${m}`, full:`${h}:${m}:${s}` };
  };
  const [time, setTime] = useStateH(fmt);
  useEffectH(() => {
    const t = setInterval(() => setTime(fmt()), 1000);
    return () => clearInterval(t);
  }, []);

  const now      = new Date();
  const dateStr  = now.toLocaleDateString('en-ZA',{weekday:'long',day:'numeric',month:'long',year:'numeric'});
  const hour     = parseInt(time.hm.split(':')[0], 10);
  const greeting = hour < 12 ? 'Good morning' : hour < 18 ? 'Good afternoon' : 'Good evening';

  return (
    <div className="page-content">
      <div className="page-head" style={{ marginBottom:20 }}>
        <div className="page-head-inner">
          <div className="page-head-split">
            <div className="page-head-left">
              <div className="page-head-eyebrow">TODAY</div>
              <h1>{greeting}, <span className="accent">Tiaan</span></h1>
              <div style={{ fontSize:14, color:'var(--ink-3)', marginTop:2 }}>{dateStr}</div>
            </div>
            <div className="page-head-right">
              <div className="live-clock">{time.full}</div>
              <div className="live-status" style={{ justifyContent:'flex-end' }}>
                <div className="pulse-dot" />
                Live · {time.hm}
              </div>
            </div>
          </div>
        </div>
      </div>

      <div className="home-grid">
        <div className="home-main">
          <WeatherCard />
          <CalendarCard />
          <YearlyCalendarCard />
          <PipelineCard />
        </div>
        <div className="home-side">
          <YouTubeCard />
          <InboxCard />
          <ScheduledCard />
          <TodoCard />
          <NotesCard />
          <ActivityCard />
        </div>
      </div>
    </div>
  );
}

/* ── Export ──────────────────────────────────────────────────────── */
window.HomePage = HomePage;
