/* tenroin-top/calendar.jsx — イベント・カレンダー（月グリッド＋店舗/カテゴリ フィルタ＋一覧）
   データは /api/tenroin/events からライブ取得。失敗時は data.jsx の EVENTS_FALLBACK。
   <EventCalendar/> … 専用ページ用フル機能
   <EventsDigest/>  … マガジン 02 節用の抜粋ダイジェスト */

const STORE_FILTERS = ['全体','東京','名古屋','京都','福岡'];

/* ---- 共有フック：イベント取得（ライブ→フォールバック） ---- */
function useEvents(){
  const [st,setSt] = React.useState({ status:'loading', events:[], live:false, updatedAt:null });
  React.useEffect(()=>{
    /* 2026/9/7＝期限は 15秒・一度だけやり直す・それでも読めなければ架空の控えを出さず「取得できませんでした」（読めないときに嘘を出さない） */
    let alive=true;
    let ctrl=null;
    const attempt = (n)=>{
      ctrl=new AbortController();
      const timer=setTimeout(()=>ctrl.abort(),15000);
      fetch('/api/tenroin/events',{ signal:ctrl.signal, headers:{ Accept:'application/json' } })
        .then(r=>{ if(!r.ok) throw new Error('bad'); return r.json(); })
        .then(d=>{ if(!alive) return; clearTimeout(timer);
          setSt({ status:'live', events:d.events||[], live:true, updatedAt:d.updatedAt }); })
        .catch(()=>{ if(!alive) return; clearTimeout(timer);
          if(n<1){ setTimeout(()=>{ if(alive) attempt(n+1); }, 1500); return; }
          setSt({ status:'error', events:[], live:false, updatedAt:null }); });
    };
    attempt(0);
    return ()=>{ alive=false; if(ctrl) ctrl.abort(); };
  },[]);
  return st;
}

const catColor = (c)=> (window.MAG.CAT_COLORS[c] || { fg:'var(--slate-700)', bg:'var(--paper-100)', dot:'var(--slate-400)' });
const ymd = (d)=> `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;

/* 店舗フィルタ：店舗選択時は その店舗＋「全国」を表示 */
function matchStore(ev, store){ return store==='全体' || ev.store===store || ev.store==='全国'; }
function matchCats(ev, cats){ return cats.size===0 || cats.has(ev.category); }

/* ============================ カテゴリ凡例 ============================ */
function CatLegend({ cats, onToggle }){
  const all = Object.keys(window.MAG.CAT_COLORS);
  return (
    <div className="cal-cats" role="group" aria-label="カテゴリで絞り込み">
      {all.map(c=>{
        const col=catColor(c), on=cats.has(c);
        return (
          <button key={c} className={'cal-cat'+(on?' is-on':'')} data-category={c}
            onClick={()=>onToggle(c)}
            style={on?{ background:col.fg, borderColor:col.fg, color:'#fff' }:{ borderColor:col.dot, color:col.fg }}>
            <span className="cc-dot" style={{ background:on?'#fff':col.dot }}></span>{c}
          </button>
        );
      })}
    </div>
  );
}

/* ============================ 月グリッド ============================ */
function MonthGrid({ month, events, onPrev, onNext, onPickDay, selectedDay }){
  const DOWH = ['日','月','火','水','木','金','土'];
  const today = new Date(); const todayStr = ymd(today);
  const y=month.getFullYear(), m=month.getMonth();
  const first=new Date(y,m,1), startDow=first.getDay();
  const daysIn=new Date(y,m+1,0).getDate();
  const byDate={};
  events.forEach(ev=>{ (byDate[ev.date]=byDate[ev.date]||[]).push(ev); });

  const cells=[];
  for(let i=0;i<startDow;i++) cells.push(null);
  for(let d=1;d<=daysIn;d++) cells.push(new Date(y,m,d));
  while(cells.length%7!==0) cells.push(null);

  return (
    <div className="cal-grid-wrap">
      <div className="cal-bar">
        <button className="cal-nav" onClick={onPrev} aria-label="前の月">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M15 6l-6 6 6 6"/></svg>
        </button>
        <div className="cal-month"><b>{y}</b><span>.</span><b>{String(m+1).padStart(2,'0')}</b>
          <i>{['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'][m]}</i></div>
        <button className="cal-nav" onClick={onNext} aria-label="次の月">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M9 6l6 6-6 6"/></svg>
        </button>
      </div>
      <div className="cal-grid">
        {DOWH.map((d,i)=><div key={d} className={'cal-dowh'+(i===0?' is-sun':'')+(i===6?' is-sat':'')}>{d}</div>)}
        {cells.map((cell,i)=>{
          if(!cell) return <div key={i} className="cal-cell is-empty"></div>;
          const ds=ymd(cell), evs=byDate[ds]||[];
          const isToday=ds===todayStr, isSel=ds===selectedDay, dow=cell.getDay();
          return (
            <div key={i} className={'cal-cell'+(isToday?' is-today':'')+(isSel?' is-sel':'')+(evs.length?' has-ev':'')}
              onClick={()=>evs.length&&onPickDay(isSel?null:ds)}>
              <span className={'cal-dn'+(dow===0?' is-sun':'')+(dow===6?' is-sat':'')}>{cell.getDate()}</span>
              <div className="cal-chips">
                {evs.slice(0,3).map((ev,j)=>{
                  const col=catColor(ev.category);
                  return <span key={j} className="cal-chip" style={{ background:col.bg, color:col.fg }} title={ev.title}>
                    <span className="cal-chip-dot" style={{ background:col.dot }}></span>{ev.category}</span>;
                })}
                {evs.length>3 && <span className="cal-more">＋{evs.length-3}件</span>}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ============================ 一覧 ============================ */
function EventList({ events, selectedDay, listRef }){
  // 当日以降を時系列で
  const todayStr = ymd(new Date());
  let rows = events.filter(e=>e.date>=todayStr).sort((a,b)=> a.date<b.date?-1:a.date>b.date?1:(a.time||'').localeCompare(b.time||''));
  if(selectedDay) rows = rows.filter(e=>e.date===selectedDay);

  // 月見出しで区切る
  const groups=[]; let cur=null;
  rows.forEach(ev=>{ const key=ev.date.slice(0,7);
    if(!cur||cur.key!==key){ cur={ key, label:`${+key.slice(5,7)}月`, items:[] }; groups.push(cur); }
    cur.items.push(ev);
  });

  return (
    <div className="cal-list" ref={listRef}>
      {selectedDay && (
        <div className="cal-list-filternote">
          <span>{selectedDay.replace(/-/g,'.').slice(5)} の催し</span>
        </div>
      )}
      {rows.length===0 ? (
        <div className="cal-empty">{st.status==='error' ? 'いま催しの一覧を取得できませんでした。少し置いて、もう一度お開きください。' : 'この条件の催しは見つかりませんでした。フィルタを変えてみてください。'}</div>
      ) : groups.map(g=>(
        <div className="cal-monthgroup" key={g.key}>
          <div className="cal-mg-head"><span className="cal-mg-no">{g.label}</span><span className="cal-mg-rule"></span><span className="cal-mg-ct">{g.items.length}件</span></div>
          {g.items.map((ev,i)=>{
            const col=catColor(ev.category);
            return (
              <a key={i} className="cal-row" href={ev.bookUrl||ev.infoUrl||'#'} target="_blank" rel="noopener"
                 onClick={e=>{ if(!ev.bookUrl) e.preventDefault(); }}
                 data-store={ev.store} data-category={ev.category} data-event-date={ev.date}>
                <span className="cal-row-date"><b>{ev.label}</b><i>{ev.weekday}</i></span>
                <span className="cal-row-time">{ev.time}</span>
                <span className="cal-row-badges">
                  <span className="cal-store-badge">{ev.store}</span>
                  <span className="cal-cat-badge" style={{ background:col.bg, color:col.fg }}>
                    <span className="cal-chip-dot" style={{ background:col.dot }}></span>{ev.category}</span>
                </span>
                <span className="cal-row-title">{ev.title}</span>
                <span className="cal-row-go">{ev.bookUrl?'詳しく・予約':'店舗ページへ'}<i>▸</i></span>
              </a>
            );
          })}
        </div>
      ))}
    </div>
  );
}

/* ============================ フル・カレンダー（専用ページ） ============================ */
function EventCalendar(){
  const st = useEvents();
  const [store,setStore] = React.useState('全体');
  const [cats,setCats] = React.useState(new Set());
  const [month,setMonth] = React.useState(()=>{ const d=new Date(); return new Date(d.getFullYear(), d.getMonth(), 1); });
  const [selDay,setSelDay] = React.useState(null);
  const listRef = React.useRef(null);

  const toggleCat = (c)=> setCats(prev=>{ const n=new Set(prev); n.has(c)?n.delete(c):n.add(c); return n; });
  const reset = ()=>{ setStore('全体'); setCats(new Set()); setSelDay(null); };

  const filtered = st.events.filter(e=>matchStore(e,store)&&matchCats(e,cats));
  const hasFilter = store!=='全体' || cats.size>0 || selDay;

  const pickDay = (ds)=>{ setSelDay(ds);
    if(ds && listRef.current){ const top=listRef.current.getBoundingClientRect().top+window.scrollY-90; window.scrollTo({ top, behavior:'smooth' }); } };

  return (
    <div className="cal-root ti" data-section="events">
      <div className="cal-filters" data-reveal>
        <div className="cal-stores" role="group" aria-label="店舗で絞り込み">
          {STORE_FILTERS.map(s=>(
            <button key={s} className={'cal-store'+(store===s?' is-on':'')} data-store={s}
              onClick={()=>{ setStore(s); setSelDay(null); }}>{s}</button>
          ))}
        </div>
        <CatLegend cats={cats} onToggle={(c)=>{ toggleCat(c); setSelDay(null); }}/>
        <div className="cal-meta">
          {hasFilter && <button className="cal-reset" onClick={reset}>条件をリセット<i>×</i></button>}
          <span className={'cal-live'+(st.live?' is-on':'')}>
            <span className="cal-live-dot"></span>{st.status==='loading'?'更新中':(st.live?'LIVE 更新':'最新日程あり')}
          </span>
        </div>
      </div>

      {st.status==='loading' ? (
        <div className="cal-skel">
          <div className="cal-skel-grid">{Array.from({length:35}).map((_,i)=><div key={i} className="cal-skel-cell"></div>)}</div>
        </div>
      ) : (
        <MonthGrid month={month} events={filtered}
          onPrev={()=>{ setMonth(new Date(month.getFullYear(), month.getMonth()-1, 1)); setSelDay(null); }}
          onNext={()=>{ setMonth(new Date(month.getFullYear(), month.getMonth()+1, 1)); setSelDay(null); }}
          onPickDay={pickDay} selectedDay={selDay}/>
      )}

      <div className="cal-list-head" data-reveal>
        <div>
          <div className="cal-lh-en">In the Calendar</div>
          <h2 className="cal-lh-jp">いま、出ている催し</h2>
        </div>
        <span className="cal-lh-ct">{filtered.filter(e=>e.date>=ymd(new Date())).length}件 ／ {store==='全体'?'全店':store}{cats.size>0?` ・ ${cats.size}カテゴリ`:''}</span>
      </div>

      {st.status==='loading'
        ? <div className="cal-list">{[0,1,2,3,4].map(i=><div className="cal-rowskel" key={i}><span></span><span></span></div>)}</div>
        : <EventList events={filtered} selectedDay={selDay} listRef={listRef}/>}
    </div>
  );
}

/* ============================ ダイジェスト（マガジン 02 節・軽量フィルタ付き） ============================ */
function EventsDigest(){
  const st = useEvents();
  const [store,setStore] = React.useState('全体');
  const [cats,setCats] = React.useState(new Set());
  const todayStr = ymd(new Date());

  const toggleCat = (c)=> setCats(prev=>{ const n=new Set(prev); n.has(c)?n.delete(c):n.add(c); return n; });
  const reset = ()=>{ setStore('全体'); setCats(new Set()); };
  const hasFilter = store!=='全体' || cats.size>0;

  const all = st.events.filter(e=>e.date>=todayStr && matchStore(e,store) && matchCats(e,cats))
    .sort((a,b)=> a.date<b.date?-1:a.date>b.date?1:(a.time||'').localeCompare(b.time||''));
  const LIMIT = 7;
  const rows = all.slice(0, LIMIT);
  const overflow = all.length - rows.length;

  return (
    <div className="ev-digest" data-section="events">
      <div className="ev-filters" data-reveal>
        <div className="ev-stores" role="group" aria-label="店舗で絞り込み">
          {STORE_FILTERS.map(s=>(
            <button key={s} className={'ev-store'+(store===s?' is-on':'')} data-store={s}
              onClick={()=>setStore(s)}>{s}</button>
          ))}
        </div>
        <div className="ev-cats" role="group" aria-label="分野で絞り込み">
          {Object.keys(window.MAG.CAT_COLORS).map(c=>{
            const col=catColor(c), on=cats.has(c);
            return (
              <button key={c} className={'ev-catbtn'+(on?' is-on':'')} data-category={c} onClick={()=>toggleCat(c)}
                style={on?{ background:col.fg, borderColor:col.fg, color:'#fff' }:{ borderColor:col.dot, color:col.fg }}>
                <span className="cc-dot" style={{ background:on?'#fff':col.dot }}></span>{c}
              </button>
            );
          })}
          {hasFilter && <button className="ev-reset" onClick={reset}>リセット<i>×</i></button>}
        </div>
      </div>

      {st.status==='loading' ? (
        <div className="ev-cal">{[0,1,2,3].map(i=><div className="ev-rowskel" key={i}><span></span><span></span></div>)}</div>
      ) : rows.length===0 ? (
        <div className="cal-empty">{st.status==='error' ? 'いま催しの一覧を取得できませんでした。少し置いて、もう一度お開きください。' : 'この条件の催しは見つかりませんでした。フィルタを変えるか、カレンダーをご覧ください。'}</div>
      ) : (
        <div className="ev-cal">
          {rows.map((ev,i)=>{
            const col=catColor(ev.category);
            return (
              <a className="ev-row" key={ev.date+ev.title+i} href={ev.bookUrl||ev.infoUrl||'#'} target="_blank" rel="noopener"
                 onClick={e=>{ if(!ev.bookUrl) e.preventDefault(); }}
                 data-store={ev.store} data-category={ev.category} data-event-date={ev.date}>
                <div className="ev-date">
                  <span className="ed-md">{ev.label}</span>
                  <span className="ed-dow">{ev.weekday}</span>
                  <span className="ed-time">OPEN {ev.time}</span>
                </div>
                <div className="ev-main">
                  <div className="ev-cat">
                    <span className="ev-catbadge" style={{ background:col.bg, color:col.fg }}>
                      <span className="cal-chip-dot" style={{ background:col.dot }}></span>{ev.category}</span>
                    <span className="ev-place">{ev.store}</span>
                  </div>
                  <h3 className="ev-ttl">{ev.title}</h3>
                </div>
                <div className="ev-go">
                  <span className="ev-book">{ev.bookUrl?'予約する':'詳しく見る'}<span>▸</span></span>
                </div>
              </a>
            );
          })}
        </div>
      )}
      <div className="ev-foot" data-reveal>
        {overflow>0 && <span className="ev-overflow">ほか {overflow}件 — カレンダーで</span>}
        <a className="melt-cta" href="events.html" data-cta="to-calendar">イベント・カレンダーを見る<span className="ar">▸</span></a>
      </div>
    </div>
  );
}

Object.assign(window, { useEvents, EventCalendar, EventsDigest });
