// ============ Calendar page ============

// Mock some journal entries so indicator dots are visible
const SEED_JOURNAL_DATES = ['2026-04-01','2026-04-07','2026-04-09','2026-04-14','2026-04-17','2026-04-21'];
const hasJournalFor = (dateStr) => {
  if (SEED_JOURNAL_DATES.includes(dateStr)) return true;
  try {
    const j = JSON.parse(localStorage.getItem('edgebook:journals') || '{}');
    return !!j[dateStr];
  } catch { return false; }
};

const CalendarPage = () => {
  const { t, fmtCurShort, fmtCur, lang } = useI18n();
  const { filteredTrades } = useAccounts();
  const today = new Date(2026, 3, 21);
  const [cur, setCur] = useState(new Date(2026, 3, 1));
  const [view, setView] = useState('month'); // month | year
  const [selectedDay, setSelectedDay] = useState(null);

  // All closed trades keyed by yyyy-mm-dd
  const CAL_LOCAL = useMemo(() => {
    const m = new Map();
    filteredTrades.filter(t=>t.status==='closed').forEach(t=>{
      const k = t.date.toISOString().slice(0,10);
      const cur = m.get(k) || { pnl: 0, count: 0, trades: [] };
      cur.pnl += t.pnl; cur.count++;
      cur.trades.push(t);
      m.set(k, cur);
    });
    return m;
  }, [filteredTrades]);

  const y = cur.getFullYear(), m = cur.getMonth();
  const first = new Date(y, m, 1);
  const last = new Date(y, m+1, 0);
  const startDow = (first.getDay() + 6) % 7;
  const daysInMonth = last.getDate();
  const prevMonthDays = new Date(y, m, 0).getDate();

  const cells = [];
  for (let i=0;i<startDow;i++){
    const d = new Date(y, m-1, prevMonthDays - startDow + i + 1);
    cells.push({ d, out:true });
  }
  for (let i=1;i<=daysInMonth;i++){ cells.push({ d: new Date(y, m, i), out:false }); }
  while (cells.length % 7 !== 0 || cells.length < 42) {
    const ld = cells[cells.length-1].d;
    cells.push({ d: new Date(ld.getFullYear(), ld.getMonth(), ld.getDate()+1), out:true });
    if (cells.length >= 42) break;
  }

  let monthPnl = 0, monthCount = 0, bestDayKey = null, worstDayKey = null, bestDayPnl = 0, worstDayPnl = 0;
  for (const c of cells) {
    if (c.out) continue;
    const k = c.d.toISOString().slice(0,10);
    const v = CAL_LOCAL.get(k);
    if (v) {
      monthPnl += v.pnl; monthCount += v.count;
      if (v.pnl > bestDayPnl) { bestDayPnl = v.pnl; bestDayKey = k; }
      if (v.pnl < worstDayPnl) { worstDayPnl = v.pnl; worstDayKey = k; }
    }
  }
  const inMonthKeys = cells.filter(c=>!c.out).map(c=>c.d.toISOString().slice(0,10));
  const maxAbsPnl = Math.max(1, ...inMonthKeys.map(k => Math.abs(CAL_LOCAL.get(k)?.pnl||0)));

  const weeks = [];
  for (let i=0;i<6;i++){
    const wk = cells.slice(i*7, i*7+7);
    let pnl=0, count=0;
    for (const c of wk) { if (c.out) continue; const v = CAL_LOCAL.get(c.d.toISOString().slice(0,10)); if (v){ pnl += v.pnl; count += v.count; } }
    weeks.push({ pnl, count });
  }

  const monthName = cur.toLocaleDateString(lang==='mn'?'mn-MN':'en-US',{month:'long', year:'numeric'});
  const dowLabels = lang==='mn' ? ['Да','Мя','Лх','Пү','Ба','Бя','Ня'] : ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'];
  const tradingDays = weeks.reduce((s,w)=>s+(w.count>0?1:0),0);

  // Day-of-week performance
  const dowStats = useMemo(() => {
    const buckets = [0,1,2,3,4,5,6].map(()=>({pnl:0,count:0,wins:0,losses:0}));
    filteredTrades.filter(t=>t.status==='closed').forEach(t => {
      const dow = (t.date.getDay() + 6) % 7;
      const b = buckets[dow];
      b.pnl += t.pnl; b.count++;
      if (t.pnl > 0) b.wins++;
      else if (t.pnl < 0) b.losses++;
    });
    return buckets;
  }, [filteredTrades]);
  const dowMax = Math.max(1, ...dowStats.map(b => Math.abs(b.pnl)));

  // Year view stats
  const yearStats = useMemo(() => {
    const months = Array.from({length:12},(_,mi)=>({pnl:0,count:0,days:{}}));
    filteredTrades.filter(t=>t.status==='closed' && t.date.getFullYear()===y).forEach(t=>{
      const mi = t.date.getMonth();
      const di = t.date.getDate();
      months[mi].pnl += t.pnl;
      months[mi].count++;
      months[mi].days[di] = (months[mi].days[di] || 0) + t.pnl;
    });
    const yearPnl = months.reduce((s,mn)=>s+mn.pnl,0);
    const bestMi = months.reduce((b,mn,i)=>mn.pnl > months[b].pnl ? i : b, 0);
    const worstMi = months.reduce((b,mn,i)=>mn.pnl < months[b].pnl ? i : b, 0);
    const tradingDaysYr = months.reduce((s,mn)=>s+Object.keys(mn.days).length,0);
    return { months, yearPnl, bestMi, worstMi, tradingDaysYr };
  }, [filteredTrades, y]);

  return (
    <div className="page">
      <PageHead
        title={t('nav_calendar')}
        sub={t('cal_sub')}
        actions={<>
          <div className="seg">
            <button className={view==='month'?'on':''} onClick={()=>setView('month')}>{t('month_view')||'Month'}</button>
            <button className={view==='year'?'on':''} onClick={()=>setView('year')}>{t('year_view')||'Year'}</button>
          </div>
          {view==='month' && <>
            <button className="btn" onClick={()=>setCur(new Date(y, m-1, 1))}><Icon name="chevron-left" size={13}/></button>
            <button className="btn" onClick={()=>setCur(new Date(today.getFullYear(), today.getMonth(), 1))}>{t('today')}</button>
            <button className="btn" onClick={()=>setCur(new Date(y, m+1, 1))}><Icon name="chevron-right" size={13}/></button>
          </>}
          {view==='year' && <>
            <button className="btn" onClick={()=>setCur(new Date(y-1, 0, 1))}><Icon name="chevron-left" size={13}/></button>
            <button className="btn" onClick={()=>setCur(new Date(today.getFullYear(), 0, 1))}>{t('today')}</button>
            <button className="btn" onClick={()=>setCur(new Date(y+1, 0, 1))}><Icon name="chevron-right" size={13}/></button>
          </>}
        </>}
      />

      {view === 'month' && (
      <>
      <div className="card card-pad mb-16" style={{display:'flex',alignItems:'center',gap:28,padding:'14px 20px',flexWrap:'wrap'}}>
        <div>
          <div className="tiny muted">{t('month')}</div>
          <div style={{fontSize:18,fontWeight:600,letterSpacing:'-0.015em'}}>{monthName}</div>
        </div>
        <div style={{height:32,width:1,background:'var(--border)'}}/>
        <div>
          <div className="tiny muted">{t('kpi_net_pnl')}</div>
          <div className={'mono ' + (monthPnl>=0?'up':'dn')} style={{fontSize:20,fontWeight:600}}>{fmtCur(monthPnl)}</div>
        </div>
        <div>
          <div className="tiny muted">{t('trading_days')}</div>
          <div className="mono" style={{fontSize:20,fontWeight:600}}>{tradingDays}</div>
        </div>
        <div>
          <div className="tiny muted">{t('th_trades')}</div>
          <div className="mono" style={{fontSize:20,fontWeight:600}}>{monthCount}</div>
        </div>
        <div>
          <div className="tiny muted">{t('avg_per_day')}</div>
          <div className={'mono ' + (monthPnl>=0?'up':'dn')} style={{fontSize:20,fontWeight:600}}>{monthCount?fmtCur(monthPnl/Math.max(1,tradingDays)):'—'}</div>
        </div>
      </div>

      <div className="cal-shell" style={{display:'grid',gridTemplateColumns:'1fr 140px',gap:16}}>
        <div>
          <div className="cal-grid" style={{marginBottom:4}}>
            {dowLabels.map(d => <div key={d} className="cal-dow">{d}</div>)}
          </div>
          <div className="cal-grid">
            {cells.map((c, i) => {
              const k = c.d.toISOString().slice(0,10);
              const v = CAL_LOCAL.get(k);
              const isToday = c.d.toDateString() === today.toDateString();
              const hasJournal = !c.out && hasJournalFor(k);
              const isBest = !c.out && k === bestDayKey && bestDayPnl > 0;
              const isWorst = !c.out && k === worstDayKey && worstDayPnl < 0;
              let cls = 'cal-day';
              if (c.out) cls += ' out';
              if (isToday) cls += ' today';
              if (v) cls += v.pnl >= 0 ? ' win' : ' loss';

              // Graded intensity
              const intensity = v ? 0.20 + 0.80 * (Math.abs(v.pnl)/maxAbsPnl) : 0;
              const style = v ? {
                background: v.pnl >= 0
                  ? `linear-gradient(135deg, rgba(16,185,129,${0.08+intensity*0.18}) 0%, rgba(16,185,129,${intensity*0.08}) 100%)`
                  : `linear-gradient(135deg, rgba(239,68,68,${0.08+intensity*0.18}) 0%, rgba(239,68,68,${intensity*0.08}) 100%)`,
                borderColor: v.pnl >= 0
                  ? `rgba(16,185,129,${0.2+intensity*0.25})`
                  : `rgba(239,68,68,${0.2+intensity*0.25})`,
              } : {};

              return (
                <div key={i} className={cls} onClick={()=>{ if (!c.out) setSelectedDay(c.d); }} style={{cursor: c.out ? 'default' : 'pointer', position:'relative', ...style}}>
                  {isBest && <div style={{position:'absolute',top:4,left:4,fontSize:11,opacity:0.85}} title={t('best_day_badge')||'Best day'}>🏆</div>}
                  {isWorst && <div style={{position:'absolute',top:4,left:4,fontSize:11,opacity:0.85}} title={t('worst_day_badge')||'Worst day'}>⚠️</div>}
                  {hasJournal && <div style={{position:'absolute',top:6,right:6,width:6,height:6,borderRadius:999,background:'rgba(245,158,11,0.8)'}} title={t('nav_journal')}/>}
                  <div className="dn-num">{c.d.getDate()}</div>
                  {v ? (
                    <>
                      <div className={'dn-pnl ' + (v.pnl>=0?'up':'dn')}>{fmtCurShort(v.pnl)}</div>
                      <div className="dn-trades">{v.count} {v.count===1?'trade':'trades'}</div>
                    </>
                  ) : (
                    !c.out && <div className="dn-trades muted" style={{marginTop:'auto'}}>—</div>
                  )}
                </div>
              );
            })}
          </div>
        </div>

        <div>
          <div className="tiny muted" style={{padding:'6px 10px',textTransform:'uppercase',letterSpacing:'0.08em',fontWeight:500}}>{t('weekly')}</div>
          <div style={{display:'flex',flexDirection:'column',gap:6,marginTop:6}}>
            {weeks.map((w,i) => (
              <div key={i} className="card" style={{padding:'10px 12px',minHeight:64,display:'flex',flexDirection:'column',justifyContent:'center'}}>
                <div className="tiny muted">{t('week')} {i+1}</div>
                <div className={'mono ' + (w.pnl>=0?'up':w.pnl<0?'dn':'neu')} style={{fontSize:14,fontWeight:600}}>{w.count?fmtCurShort(w.pnl):'—'}</div>
                <div className="tiny muted">{w.count} {t('th_trades').toLowerCase()}</div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Day of Week stats */}
      <div className="card mb-16" style={{marginTop:16}}>
        <div className="card-head">
          <div>
            <div className="card-title">{t('dow_performance')||'Day of week performance'}</div>
            <div className="card-sub">{t('dow_sub')||'See which weekday compounds your edge'}</div>
          </div>
        </div>
        <div style={{padding:'14px 20px 20px'}}>
          <div style={{display:'grid',gridTemplateColumns:'repeat(7,1fr)',gap:12}}>
            {dowStats.map((b,i)=>{
              const wr = b.count ? (b.wins/b.count)*100 : 0;
              const h = Math.max(4, (Math.abs(b.pnl)/dowMax)*120);
              const isPos = b.pnl >= 0;
              return (
                <div key={i} style={{display:'flex',flexDirection:'column',alignItems:'center',gap:6}}>
                  <div style={{fontSize:11,color:'var(--text-3)',fontFamily:'JetBrains Mono',textTransform:'uppercase',letterSpacing:'0.06em'}}>{dowLabels[i]}</div>
                  <div style={{height:130,width:'100%',display:'flex',alignItems:'flex-end',justifyContent:'center',position:'relative'}}>
                    {b.count > 0 && (
                      <div style={{
                        width:'60%',
                        height:h,
                        background: isPos ? 'linear-gradient(180deg,rgba(16,185,129,.3),rgba(16,185,129,.6))' : 'linear-gradient(180deg,rgba(239,68,68,.3),rgba(239,68,68,.6))',
                        borderTop: '2px solid ' + (isPos?'#10b981':'#ef4444'),
                        borderRadius:'4px 4px 0 0',
                      }}/>
                    )}
                  </div>
                  <div className={'mono tiny '+(b.pnl>=0?'up':b.pnl<0?'dn':'neu')} style={{fontWeight:600}}>{b.count?fmtCurShort(b.pnl):'—'}</div>
                  <div className="tiny muted">{b.count?`${wr.toFixed(0)}% · ${b.count}`:'—'}</div>
                </div>
              );
            })}
          </div>
        </div>
      </div>
      </>
      )}

      {view === 'year' && (
        <YearView y={y} yearStats={yearStats} CAL_LOCAL={CAL_LOCAL} onPickMonth={(mi)=>{ setCur(new Date(y, mi, 1)); setView('month'); }}/>
      )}

      {/* Day drawer */}
      {selectedDay && <DayDrawer day={selectedDay} trades={CAL_LOCAL.get(selectedDay.toISOString().slice(0,10))?.trades || []} onClose={()=>setSelectedDay(null)}/>}
    </div>
  );
};

// ---- Year view ----
const YearView = ({ y, yearStats, CAL_LOCAL, onPickMonth }) => {
  const { t, fmtCur, fmtCurShort, lang } = useI18n();
  const MONTH_NAMES = Array.from({length:12},(_,i)=>new Date(y,i,1).toLocaleDateString(lang==='mn'?'mn-MN':'en-US',{month:'short'}));

  // compute max abs pnl for a day across the whole year for heatmap grading
  let yMaxAbs = 1;
  for (const mn of yearStats.months) {
    for (const k of Object.keys(mn.days)) yMaxAbs = Math.max(yMaxAbs, Math.abs(mn.days[k]));
  }

  return (
    <>
      <div className="card card-pad mb-16" style={{display:'flex',alignItems:'center',gap:28,padding:'14px 20px',flexWrap:'wrap'}}>
        <div>
          <div className="tiny muted">{y}</div>
          <div style={{fontSize:18,fontWeight:600,letterSpacing:'-0.015em'}}>{t('year_view')||'Year'}</div>
        </div>
        <div style={{height:32,width:1,background:'var(--border)'}}/>
        <div>
          <div className="tiny muted">{t('year_pnl')||'Year P&L'}</div>
          <div className={'mono ' + (yearStats.yearPnl>=0?'up':'dn')} style={{fontSize:20,fontWeight:600}}>{fmtCur(yearStats.yearPnl)}</div>
        </div>
        <div>
          <div className="tiny muted">{t('trading_days')}</div>
          <div className="mono" style={{fontSize:20,fontWeight:600}}>{yearStats.tradingDaysYr}</div>
        </div>
        <div>
          <div className="tiny muted">{t('best_month')||'Best month'}</div>
          <div className="mono up" style={{fontSize:20,fontWeight:600}}>{MONTH_NAMES[yearStats.bestMi]}</div>
        </div>
        <div>
          <div className="tiny muted">{t('worst_month')||'Worst month'}</div>
          <div className="mono dn" style={{fontSize:20,fontWeight:600}}>{MONTH_NAMES[yearStats.worstMi]}</div>
        </div>
      </div>

      <div style={{display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:14}}>
        {yearStats.months.map((mn, mi) => {
          const daysIn = new Date(y, mi+1, 0).getDate();
          const firstDow = (new Date(y, mi, 1).getDay() + 6) % 7;
          // grid: 7 cols, up to 6 rows
          const cells = [];
          for (let i=0;i<firstDow;i++) cells.push(null);
          for (let d=1;d<=daysIn;d++) cells.push(d);
          while (cells.length % 7) cells.push(null);

          return (
            <div key={mi} className="card" style={{padding:'14px',cursor:'pointer',transition:'all .15s'}} onClick={()=>onPickMonth(mi)}
                 onMouseEnter={e=>{e.currentTarget.style.borderColor='var(--accent)';}}
                 onMouseLeave={e=>{e.currentTarget.style.borderColor='var(--border)';}}>
              <div style={{display:'flex',alignItems:'baseline',justifyContent:'space-between',marginBottom:10}}>
                <div style={{fontWeight:600,fontSize:13.5}}>{MONTH_NAMES[mi]}</div>
                <div className={'mono tiny '+(mn.pnl>=0?'up':mn.pnl<0?'dn':'neu')} style={{fontWeight:600}}>{mn.count?fmtCurShort(mn.pnl):'—'}</div>
              </div>
              <div style={{display:'grid',gridTemplateColumns:'repeat(7,1fr)',gap:2,marginBottom:8}}>
                {cells.map((d,ci)=>{
                  if (!d) return <div key={ci} style={{aspectRatio:'1',background:'transparent'}}/>;
                  const pnl = mn.days[d];
                  if (pnl === undefined) return <div key={ci} style={{aspectRatio:'1',background:'var(--card-2)',borderRadius:2}}/>;
                  const intensity = 0.25 + 0.75 * (Math.abs(pnl)/yMaxAbs);
                  const bg = pnl>=0 ? `rgba(16,185,129,${intensity})` : `rgba(239,68,68,${intensity})`;
                  return <div key={ci} style={{aspectRatio:'1',background:bg,borderRadius:2}} title={`${MONTH_NAMES[mi]} ${d} — ${fmtCurShort(pnl)}`}/>;
                })}
              </div>
              <div className="tiny muted">{mn.count} {t('th_trades').toLowerCase()}</div>
            </div>
          );
        })}
      </div>
    </>
  );
};

// ---- Day drawer ----
const DayDrawer = ({ day, trades, onClose }) => {
  const { t, fmtCur, lang } = useI18n();
  const totalPnl = trades.reduce((s,t)=>s+(t.pnl||0),0);
  const wins = trades.filter(t=>t.pnl>0).length;
  const avgR = trades.length ? trades.reduce((s,t)=>s+(t.r||0),0)/trades.length : 0;
  const bestTrade = trades.slice().sort((a,b)=>b.pnl-a.pnl)[0];
  const worstTrade = trades.slice().sort((a,b)=>a.pnl-b.pnl)[0];
  const key = day.toISOString().slice(0,10);
  const journal = hasJournalFor(key);
  const go = (href) => { try { localStorage.setItem('edgebook:journal_date', key); } catch {} window.location.hash = href; };

  return (
    <div className="td-scrim" onClick={onClose}>
      <div className="td-drawer" onClick={e=>e.stopPropagation()} style={{width:460}}>
        <div className="td-head">
          <div style={{flex:1}}>
            <div className="tiny muted" style={{textTransform:'uppercase',letterSpacing:'0.08em',fontWeight:500}}>
              {day.toLocaleDateString(lang==='mn'?'mn-MN':'en-US',{weekday:'long',month:'long',day:'numeric',year:'numeric'})}
            </div>
            <div className={'mono '+(totalPnl>=0?'up':totalPnl<0?'dn':'neu')} style={{fontSize:26,fontWeight:600,marginTop:6,letterSpacing:'-0.015em'}}>
              {trades.length ? fmtCur(totalPnl) : '—'}
            </div>
          </div>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={16}/></button>
        </div>
        <div className="td-body">
          {trades.length > 0 && (
            <div style={{display:'grid',gridTemplateColumns:'repeat(5,1fr)',gap:10,marginBottom:20,padding:'14px',background:'var(--card-2)',borderRadius:8}}>
              <div><div className="tiny muted">{t('th_trades')}</div><div className="mono" style={{fontWeight:600}}>{trades.length}</div></div>
              <div><div className="tiny muted">{t('winrate')||'Win %'}</div><div className="mono" style={{fontWeight:600}}>{trades.length?Math.round(wins/trades.length*100):0}%</div></div>
              <div><div className="tiny muted">{t('best_ticker')||'Best'}</div><div className="mono up" style={{fontWeight:600,fontSize:12}}>{bestTrade?.ticker||'—'}</div></div>
              <div><div className="tiny muted">{t('worst_ticker')||'Worst'}</div><div className="mono dn" style={{fontWeight:600,fontSize:12}}>{worstTrade?.ticker||'—'}</div></div>
              <div><div className="tiny muted">{t('kpi_avg_r')}</div><div className={'mono '+(avgR>=0?'up':'dn')} style={{fontWeight:600}}>{(avgR>=0?'+':'')+avgR.toFixed(2)}R</div></div>
            </div>
          )}

          <div className="td-sec-title" style={{marginBottom:8}}>{t('th_trades')}</div>
          {trades.length === 0 ? (
            <div style={{padding:'30px 0',textAlign:'center'}} className="muted tiny">{t('no_trades_this_day')||'No trades this day'}</div>
          ) : (
            <div style={{display:'flex',flexDirection:'column',gap:8}}>
              {trades.map(tr=>(
                <div key={tr.id} className="card" style={{padding:'10px 12px',cursor:'pointer'}}>
                  <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',gap:8}}>
                    <div style={{display:'flex',alignItems:'center',gap:8}}>
                      <span className="ticker" style={{fontSize:13}}>{tr.ticker}</span>
                      <DirBadge dir={tr.dir}/>
                    </div>
                    <div className={'mono '+(tr.pnl>0?'up':tr.pnl<0?'dn':'neu')} style={{fontWeight:600,fontSize:13}}>{tr.status==='open'?'—':fmtCur(tr.pnl)}</div>
                  </div>
                  <div className="muted tiny mono" style={{marginTop:4}}>{tr.date.toLocaleTimeString(lang==='mn'?'mn-MN':'en-US',{hour:'2-digit',minute:'2-digit'})} · {tr.size} @ ${tr.entry.toFixed(2)}{tr.exit?` → $${tr.exit.toFixed(2)}`:''} · {(tr.r>=0?'+':'')+tr.r.toFixed(2)}R</div>
                </div>
              ))}
            </div>
          )}

          <div className="td-sec-title" style={{marginTop:20,marginBottom:8}}>{t('nav_journal')}</div>
          {journal ? (
            <div className="card" style={{padding:'12px 14px'}}>
              <div className="muted tiny" style={{lineHeight:1.55}}>Strong follow-through on morning setups. Pre-market plan flagged NVDA as priority — stuck to it, avoided FOMO chases on secondaries...</div>
              <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginTop:10}}>
                <div style={{display:'flex',alignItems:'center',gap:8}}><span style={{fontSize:16}}>😌</span><span className="tiny muted">Calm · discipline held</span></div>
                <button className="btn btn-ghost" onClick={()=>go('#/journal')}><Icon name="edit" size={12}/> {t('edit_journal')||'Edit journal'}</button>
              </div>
            </div>
          ) : (
            <button className="btn" onClick={()=>go('#/journal')} style={{width:'100%'}}><Icon name="plus" size={13}/> {t('add_journal_entry')||'Add journal entry'}</button>
          )}
        </div>
        <div className="td-foot">
          <button className="btn btn-ghost" style={{width:'100%'}} onClick={()=>{ try{localStorage.setItem('edgebook:trades_filter.date', key);}catch{} window.location.hash = '#/trades'; }}>
            <Icon name="eye" size={13}/> {t('view_all_trades_day')||'View all trades that day'}
          </button>
        </div>
      </div>
    </div>
  );
};

window.CalendarPage = CalendarPage;
