// Chart Growth Hub — Student "Upcoming events" calendar (preview + booking).
// Visible to EVERY student. Reads the public `live_calendar` view (published events,
// no join links). Booking a slot requires ACTIVE Live Trading Room access.
// Exposes window.EventsPanel.
(function(){
const { useState, useEffect, useMemo } = React;

const TYPE_META={
  live:    { label:'Live session', dot:'var(--gold-2)', soft:'rgba(212,175,55,.16)',  text:'var(--gold-2)', border:'rgba(212,175,55,.45)' },
  training:{ label:'Training',     dot:'#34d399',        soft:'rgba(52,211,153,.14)',  text:'#5fe3b4',       border:'rgba(52,211,153,.45)' },
  meeting: { label:'Meeting',      dot:'#8ab4ff',        soft:'rgba(122,162,247,.16)', text:'#a9c4ff',       border:'rgba(122,162,247,.45)' },
  maintenance:{ label:'Maintenance', dot:'#f4a52a',      soft:'rgba(244,165,42,.16)',  text:'#f6bd5c',       border:'rgba(244,165,42,.5)' },
};
const WD=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
const MO=['January','February','March','April','May','June','July','August','September','October','November','December'];
const dayKey = d => { const x=new Date(d); return x.getFullYear()+'-'+x.getMonth()+'-'+x.getDate(); };
const sameDay = (a,b) => a&&b&&dayKey(a)===dayKey(b);
const fmtTime = d => d ? new Date(d).toLocaleTimeString(undefined,{hour:'numeric',minute:'2-digit'}) : 'Time TBA';

const ebadge={display:'inline-block',padding:'4px 11px',borderRadius:999,fontFamily:'var(--font-mono)',fontSize:'.7rem',border:'1px solid var(--border-gold)'};

function EventsPanel({client, session}){
  const [events,setEvents]=useState(null);
  const [bookings,setBookings]=useState({});
  const [active,setActive]=useState(false);
  const [me,setMe]=useState(null);
  const today=new Date();
  const [cursor,setCursor]=useState(new Date(today.getFullYear(),today.getMonth(),1));
  const [selDay,setSelDay]=useState(new Date());
  const [busy,setBusy]=useState(null);
  const [err,setErr]=useState("");

  async function load(){
    const { data:ev, error } = await client.from('live_calendar').select('*').order('starts_at',{ascending:true});
    if(error){ setEvents([]); return; }
    setEvents(ev||[]);
    const { data:bk } = await client.from('live_bookings').select('session_id').eq('student_id',session.user.id);
    const bm={}; (bk||[]).forEach(r=>bm[r.session_id]=true); setBookings(bm);
    const { data:la } = await client.from('live_access').select('status').eq('student_id',session.user.id).maybeSingle();
    setActive(!!(la && la.status==='active'));
    const { data:s } = await client.from('students').select('full_name,email').eq('id',session.user.id).maybeSingle();
    setMe(s);
  }
  useEffect(()=>{ load(); },[]);

  async function book(ev){
    setBusy(ev.id); setErr("");
    const { error } = await client.from('live_bookings').insert({ session_id:ev.id, student_id:session.user.id,
      student_email:(me&&me.email)||session.user.email, student_name:(me&&me.full_name)||null });
    if(error){ setErr(error.message); }
    else { setBookings(b=>({...b,[ev.id]:true})); try{ client.functions.invoke('notify-event',{ body:{ kind:'booked', session_id:ev.id } }); }catch(e){}
           if(window.cgLog) window.cgLog(client,'book_event', ev.title||'event');
           setEvents(es=>es.map(x=>x.id===ev.id?{...x,attendee_count:(+x.attendee_count||0)+1}:x)); }
    setBusy(null);
  }
  async function cancel(ev){
    setBusy(ev.id);
    await client.from('live_bookings').delete().eq('session_id',ev.id).eq('student_id',session.user.id);
    setBookings(b=>{ const n={...b}; delete n[ev.id]; return n; });
    setEvents(es=>es.map(x=>x.id===ev.id?{...x,attendee_count:Math.max(0,(+x.attendee_count||1)-1)}:x));
    setBusy(null);
  }

  const monthCells = useMemo(()=>{
    const y=cursor.getFullYear(), m=cursor.getMonth();
    const start=new Date(y,m,1).getDay(); const dim=new Date(y,m+1,0).getDate();
    const cells=[]; for(let i=0;i<start;i++) cells.push(null);
    for(let d=1;d<=dim;d++) cells.push(new Date(y,m,d));
    while(cells.length%7) cells.push(null);
    return cells;
  },[cursor]);
  const byDay = useMemo(()=>{ const map={}; (events||[]).forEach(s=>{ if(!s.starts_at) return; (map[dayKey(s.starts_at)]=map[dayKey(s.starts_at)]||[]).push(s); }); return map; },[events]);
  const dayEvents = (selDay && byDay[dayKey(selDay)]) || [];
  const nextUp = useMemo(()=> (events||[]).filter(s=>s.starts_at && new Date(s.starts_at).getTime()>Date.now()-3*3600e3).slice(0,3), [events]);

  if(events===null) return null;
  if(events.length===0) return null;   // nothing published yet — stay quiet

  return <div style={{marginBottom:34}}>
    <div style={{display:'flex',justifyContent:'space-between',alignItems:'baseline',gap:14,flexWrap:'wrap',marginBottom:6}}>
      <h2 style={{fontSize:'1.4rem'}}>Upcoming events &amp; live sessions</h2>
      {!active && <span style={{fontFamily:'var(--font-mono)',fontSize:'.74rem',color:'var(--ink-faint)'}}>Booking needs Live Trading Room access</span>}
    </div>
    <p style={{color:'var(--ink-dim)',fontSize:'.92rem',marginBottom:16,maxWidth:620}}>Trainings, live sessions and meetings your coaches have scheduled. Pick a day to see what's on{active?' and book your slot.':' — get Live access to book your slot.'}</p>

    <div style={{display:'flex',gap:20,flexWrap:'wrap',alignItems:'flex-start',background:'linear-gradient(165deg,var(--surface-2),var(--surface))',border:'1px solid var(--border)',borderRadius:'var(--radius)',padding:'22px'}}>
      {/* legend */}
      <div style={{flex:'1 1 440px',minWidth:300}}>
        <div style={{display:'flex',gap:14,flexWrap:'wrap',marginBottom:14}}>
          {Object.entries(TYPE_META).map(([k,m])=>(
            <span key={k} style={{display:'inline-flex',alignItems:'center',gap:7,fontSize:'.76rem',color:'var(--ink-dim)',fontFamily:'var(--font-mono)'}}>
              <span style={{width:10,height:10,borderRadius:3,background:m.dot}}></span>{m.label}</span>))}
        </div>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:12}}>
          <div style={{fontSize:'1.05rem',fontWeight:600}}>{MO[cursor.getMonth()]} {cursor.getFullYear()}</div>
          <div style={{display:'flex',gap:7}}>
            <EBtn onClick={()=>setCursor(new Date(cursor.getFullYear(),cursor.getMonth()-1,1))}>←</EBtn>
            <EBtn onClick={()=>{const n=new Date(); setCursor(new Date(n.getFullYear(),n.getMonth(),1)); setSelDay(n);}}>Today</EBtn>
            <EBtn onClick={()=>setCursor(new Date(cursor.getFullYear(),cursor.getMonth()+1,1))}>→</EBtn>
          </div>
        </div>
        <div style={{display:'grid',gridTemplateColumns:'repeat(7,1fr)',gap:6}}>
          {WD.map(d=><div key={d} style={{textAlign:'center',fontFamily:'var(--font-mono)',fontSize:'.64rem',letterSpacing:'.1em',textTransform:'uppercase',color:'var(--ink-faint)',paddingBottom:4}}>{d}</div>)}
          {monthCells.map((d,i)=>{
            if(!d) return <div key={i}></div>;
            const evs=byDay[dayKey(d)]||[]; const isToday=sameDay(d,today); const isSel=sameDay(d,selDay);
            return <button key={i} onClick={()=>setSelDay(d)} style={{textAlign:'left',minHeight:64,padding:'6px 7px',borderRadius:10,cursor:'pointer',
              background:isSel?'var(--gold-soft)':'var(--navy-950)', border:'1px solid '+(isSel||isToday?'var(--border-gold)':'var(--border)'),
              display:'flex',flexDirection:'column',gap:3,overflow:'hidden'}}>
              <span style={{display:'flex',justifyContent:'space-between',alignItems:'center'}}>
                <span style={{fontFamily:'var(--font-mono)',fontSize:'.72rem',fontWeight:isToday?700:500,color:isToday?'var(--gold-2)':'var(--ink-dim)'}}>{d.getDate()}</span>
                {bookings && evs.some(e=>bookings[e.id]) && <span style={{width:6,height:6,borderRadius:'50%',background:'var(--green)'}}></span>}
              </span>
              <span style={{display:'flex',gap:3,flexWrap:'wrap'}}>
                {evs.slice(0,4).map(s=>{ const m=TYPE_META[s.session_type]||TYPE_META.live;
                  return <span key={s.id} style={{width:7,height:7,borderRadius:'50%',background:m.dot}}></span>; })}
              </span>
            </button>;
          })}
        </div>
      </div>

      {/* day detail */}
      <div style={{flex:'1 1 300px',minWidth:270}}>
        <div style={{fontWeight:600,fontSize:'1rem',marginBottom:12}}>{selDay? selDay.toLocaleDateString(undefined,{weekday:'long',month:'long',day:'numeric'}) : 'Select a day'}</div>
        {err && <div style={{color:'var(--red)',fontSize:'.8rem',fontFamily:'var(--font-mono)',marginBottom:10}}>{err}</div>}
        {dayEvents.length===0 && <div style={{padding:'24px 16px',textAlign:'center',color:'var(--ink-faint)',border:'1px dashed var(--border)',borderRadius:'var(--radius-sm)',fontSize:'.88rem'}}>
          Nothing on this day.{nextUp.length>0 && <div style={{marginTop:10,fontSize:'.8rem'}}>Next: <span style={{color:'var(--gold-2)',cursor:'pointer'}} onClick={()=>{const d=new Date(nextUp[0].starts_at); setCursor(new Date(d.getFullYear(),d.getMonth(),1)); setSelDay(d);}}>{nextUp[0].title} →</span></div>}
        </div>}
        <div style={{display:'grid',gap:11}}>
          {dayEvents.map(ev=>{
            const m=TYPE_META[ev.session_type]||TYPE_META.live; const booked=!!bookings[ev.id]; const b=busy===ev.id;
            return <div key={ev.id} style={{padding:'15px 16px',border:'1px solid '+(booked?'rgba(52,211,153,.45)':m.border),borderRadius:'var(--radius-sm)',background:'var(--navy-950)'}}>
              <div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap',marginBottom:6}}>
                <span style={{...ebadge,color:m.text,background:m.soft,borderColor:m.border}}>{m.label}</span>
                {booked && <span style={{...ebadge,color:'#5fe3b4',background:'rgba(52,211,153,.14)',borderColor:'rgba(52,211,153,.45)'}}>✓ Booked</span>}
              </div>
              <div style={{fontWeight:600,fontSize:'1.02rem'}}>{ev.title}</div>
              <div style={{fontFamily:'var(--font-mono)',fontSize:'.74rem',color:'var(--ink-faint)',marginTop:4}}>{fmtTime(ev.starts_at)}{ev.duration?' · '+ev.duration:''}{ev.coach_name?' · '+ev.coach_name:''}{(+ev.attendee_count>0)?' · '+ev.attendee_count+' attending':''}</div>
              {ev.description && <p style={{color:'var(--ink-dim)',fontSize:'.86rem',marginTop:8}}>{ev.description}</p>}
              <div style={{marginTop:12}}>
                {ev.session_type==='maintenance'
                  ? <div style={{fontFamily:'var(--font-mono)',fontSize:'.76rem',color:'#f6bd5c',padding:'8px 0'}}>⚠ Scheduled maintenance — the platform may be briefly unavailable. No booking needed.</div>
                  : active
                    ? (booked
                        ? <button className="btn btn-ghost" style={{width:'auto',padding:'9px 16px'}} disabled={b} onClick={()=>cancel(ev)}>{b?'…':'Cancel my slot'}</button>
                        : <button className="btn btn-primary" style={{width:'auto',padding:'9px 18px'}} disabled={b} onClick={()=>book(ev)}>{b?<><span className="cg-spin"></span> Booking…</>:'Book my slot'}</button>)
                    : <div style={{fontFamily:'var(--font-mono)',fontSize:'.76rem',color:'var(--ink-faint)',padding:'8px 0'}}>🔒 Live Trading Room access needed to book.</div>}
              </div>
            </div>;
          })}
        </div>
      </div>
    </div>
  </div>;
}

function EBtn({children,onClick}){
  return <button onClick={onClick} style={{padding:'7px 13px',borderRadius:8,cursor:'pointer',fontFamily:'var(--font-body)',fontWeight:600,fontSize:'.8rem',border:'1px solid var(--border)',background:'var(--surface)',color:'var(--ink)'}}>{children}</button>;
}

window.EventsPanel = EventsPanel;
})();
