// GK Components — presentational pieces for the board dashboard.
const { fmt, cleanName, monthShort, monthLong } = window.GKAnalysis;

function fmtPct(p) {
  if (p == null) return 'new';
  if (!isFinite(p)) return 'new';
  return (p >= 1000 ? '>999' : Math.round(p)) + '%';
}

function Delta({ cur, prior, invert, suffix }) {
  if (cur == null || prior == null) return <span className="delta neutral">no prior</span>;
  const diff = cur - prior;
  if (Math.abs(diff) < 1) return <span className="delta neutral">flat vs LY</span>;
  const up = diff > 0;
  const good = invert ? !up : up;
  return (
    <span className={'delta ' + (good ? 'good' : 'bad')}>
      {up ? '▲' : '▼'} {fmt(Math.abs(diff))} vs LY{suffix || ''}
    </span>
  );
}

function KpiCard({ title, value, prior, invert, note, onClick, active }) {
  return (
    <button type="button" className={'kpi-card' + (active ? ' active' : '')} onClick={onClick}>
      <div className="kpi-title">{title}</div>
      <div className={'kpi-value' + (value != null && value < 0 ? ' neg' : '')}>{fmt(value)}</div>
      <Delta cur={value} prior={prior} invert={invert}></Delta>
      {note ? <div className="kpi-note">{note}</div> : null}
      <div className="kpi-hint">{active ? 'hide details \u25b4' : 'details \u25be'}</div>
    </button>
  );
}

function DrillPanel({ drill, onClose }) {
  if (!drill) return null;
  return (
    <div className="panel drill-panel">
      <div className="drill-head">
        <h2 className="panel-h drill-h">{drill.title}</h2>
        <button className="ghost-btn" onClick={onClose}>Close</button>
      </div>
      <table className="drill-table">
        <thead>
          <tr><th></th><th>This year</th><th>Last year</th><th>Change</th></tr>
        </thead>
        <tbody>
          {drill.rows.map((r, i) => {
            const diff = r.cur - r.prior;
            const moved = Math.abs(diff) >= 1;
            const good = r.invert ? diff < 0 : diff > 0;
            return (
              <tr key={i} className={(r.bold ? 'drill-bold ' : '') + (r.rule ? 'drill-rule' : '')}>
                <td className={r.indent ? 'drill-indent' : ''}>{r.name}</td>
                <td className="drill-num">{fmt(r.cur)}</td>
                <td className="drill-num drill-dim">{fmt(r.prior)}</td>
                <td className={'drill-num ' + (!moved ? 'drill-dim' : good ? 'good' : 'bad')}>
                  {!moved ? 'flat' : (diff > 0 ? '+' : '\u2212') + fmt(Math.abs(diff))}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
      {drill.note ? <div className="panel-foot">{drill.note}</div> : null}
    </div>
  );
}

function SevDot({ severity }) {
  return <span className={'sev-dot sev-' + severity}></span>;
}

function FlagCard({ flag }) {
  const isNew = flag.prior === 0;
  return (
    <div className={'flag-card sevline-' + flag.severity}>
      <div className="flag-head">
        <SevDot severity={flag.severity}></SevDot>
        <span className="flag-name">{flag.name}</span>
        <span className="flag-scope">{flag.scope}</span>
      </div>
      <div className="flag-nums">
        <span className="flag-cur">{fmt(flag.cur)}</span>
        <span className="flag-vs">vs {fmt(flag.prior)} LY</span>
        <span className={'flag-diff ' + (flag.favorable ? 'good' : 'bad')}>
          {flag.diff > 0 ? '+' : '−'}{fmt(Math.abs(flag.diff))} · {isNew ? 'new' : fmtPct(flag.pct)}
        </span>
      </div>
      {flag.context ? <div className="flag-context">{flag.context}</div> : null}
    </div>
  );
}

function ClassCard({ cls, seasonal, onClick, active }) {
  const items = [
    { k: 'Revenue', v: cls.income },
    { k: 'Expenses', v: cls.expense },
  ];
  return (
    <button type="button" className={'class-card' + (active ? ' class-card-active' : '')} onClick={onClick}>
      <div className="class-head">
        <span className="class-name">{cls.name}</span>
        {seasonal ? <span className="class-tag">seasonal</span> : null}
      </div>
      <div className={'class-net' + (cls.net != null && cls.net < 0 ? ' neg' : '')}>{fmt(cls.net)}</div>
      <div className="class-netlabel">net this month</div>
      <div className="class-rows">
        {items.map((it) => (
          <div className="class-row" key={it.k}>
            <span>{it.k}</span><span>{fmt(it.v)}</span>
          </div>
        ))}
      </div>
      <div className="kpi-hint">{active ? 'hide ▴' : 'details ▾'}</div>
    </button>
  );
}

function ClassDrillPanel({ detail, onClose }) {
  if (!detail) return null;
  const { title, rows, prevLabel, lyLabel } = detail;
  return (
    <div style={{ marginTop: 16, borderTop: '2px solid var(--line)', paddingTop: 16 }}>
      <div className="drill-head" style={{ marginBottom: 12 }}>
        <h3 style={{ margin: 0, fontFamily: 'var(--serif)', fontSize: 16, fontWeight: 400, color: 'var(--ink)' }}>
          {title}
        </h3>
        <button className="ghost-btn" onClick={onClose}>Close</button>
      </div>
      <table className="drill-table">
        <thead>
          <tr>
            <th></th>
            <th>This month</th>
            {prevLabel ? <th>vs {prevLabel}</th> : null}
            {lyLabel ? <th>vs {lyLabel}</th> : null}
          </tr>
        </thead>
        <tbody>
          {rows.map((r, i) => {
            if (r.sectionHead) {
              return (
                <tr key={i}>
                  <td colSpan={2 + (prevLabel ? 1 : 0) + (lyLabel ? 1 : 0)} style={{
                    paddingTop: 14, paddingBottom: 3,
                    fontSize: 11, textTransform: 'uppercase',
                    letterSpacing: '1.2px', color: 'var(--ink-soft)',
                    fontWeight: 600, borderBottom: '1px solid var(--line)'
                  }}>{r.name}</td>
                </tr>
              );
            }
            const diff = r.prior != null ? r.cur - r.prior : null;
            const moved = diff != null && Math.abs(diff) >= 1;
            const good = r.invert ? (diff != null && diff < 0) : (diff != null && diff > 0);
            const lyDiff = r.ly != null ? r.cur - r.ly : null;
            const lyMoved = lyDiff != null && Math.abs(lyDiff) >= 1;
            const lyGood = r.invert ? (lyDiff != null && lyDiff < 0) : (lyDiff != null && lyDiff > 0);
            return (
              <tr key={i} className={(r.bold ? 'drill-bold ' : '') + (r.rule ? 'drill-rule' : '')}>
                <td className={r.indent ? 'drill-indent' : ''}>{r.name}</td>
                <td className="drill-num">{fmt(r.cur)}</td>
                {prevLabel ? (
                  <td className={'drill-num ' + (!moved ? 'drill-dim' : good ? 'good' : 'bad')} style={{ fontSize: 12.5 }}>
                    {r.prior == null ? '—'
                      : !moved ? '(flat)'
                      : (diff > 0 ? '(+' : '(−') + fmt(Math.abs(diff)) + ')'}
                  </td>
                ) : null}
                {lyLabel ? (
                  <td className={'drill-num ' + (!lyMoved ? 'drill-dim' : lyGood ? 'good' : 'bad')} style={{ fontSize: 12.5 }}>
                    {r.ly == null ? '—'
                      : !lyMoved ? '(flat)'
                      : (lyDiff > 0 ? '(+' : '(−') + fmt(Math.abs(lyDiff)) + ')'}
                  </td>
                ) : null}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function BalanceWatch({ items }) {
  return (
    <div className="bw-table">
      {items.map((b) => (
        <div className="bw-row" key={b.name}>
          <span className={'bw-tone tone-' + b.tone}></span>
          <span className="bw-name">{b.name}</span>
          <span className="bw-cur">{fmt(b.cur)}</span>
          <span className={'bw-diff ' + (b.tone === 'good' ? 'good' : b.tone === 'bad' ? 'bad' : '')}>
            {Math.abs(b.diff) < 1 ? 'flat' : (b.diff > 0 ? '+' : '−') + fmt(Math.abs(b.diff))} vs LY
          </span>
        </div>
      ))}
    </div>
  );
}

function SeasonChart({ series }) {
  const W = 560, H = 170, pad = 26;
  const vals = series.flatMap((s) => [s.net, s.netLY]).filter((x) => x != null);
  if (!vals.length) return <div className="empty-note">Upload more months to build the season picture.</div>;
  const max = Math.max(...vals, 0), min = Math.min(...vals, 0);
  const span = max - min || 1;
  const y = (v) => pad + (max - v) / span * (H - pad * 2);
  const bw = Math.min(44, (W - pad * 2) / Math.max(series.length, 1) * 0.34);
  const step = (W - pad * 2) / Math.max(series.length, 1);
  return (
    <svg viewBox={'0 0 ' + W + ' ' + H} className="season-chart" role="img" aria-label="Net income by month">
      <line x1={pad} x2={W - pad / 2} y1={y(0)} y2={y(0)} className="axis"></line>
      {series.map((s, i) => {
        const cx = pad + step * i + step / 2;
        return (
          <g key={s.key}>
            {s.netLY != null ? (
              <rect x={cx - bw - 2} width={bw} y={Math.min(y(0), y(s.netLY))} height={Math.abs(y(s.netLY) - y(0)) || 1} className="bar-ly"></rect>
            ) : null}
            {s.net != null ? (
              <rect x={cx + 2} width={bw} y={Math.min(y(0), y(s.net))} height={Math.abs(y(s.net) - y(0)) || 1} className={'bar ' + (s.net < 0 ? 'bar-neg' : 'bar-pos')}></rect>
            ) : null}
            <text x={cx} y={H - 6} textAnchor="middle" className="chart-label">{s.label}</text>
            {s.net != null ? (
              <text x={cx} y={(s.net < 0 ? y(s.net) + 14 : y(s.net) - 6)} textAnchor="middle" className="chart-val">{fmt(s.net)}</text>
            ) : null}
          </g>
        );
      })}
      <g className="legend">
        <rect x={W - 150} y={8} width={10} height={10} className="bar bar-pos"></rect>
        <text x={W - 136} y={17} className="chart-label">this year</text>
        <rect x={W - 76} y={8} width={10} height={10} className="bar-ly"></rect>
        <text x={W - 62} y={17} className="chart-label">last year</text>
      </g>
    </svg>
  );
}

function QuestionsList({ questions }) {
  return (
    <ol className="q-list">
      {questions.map((q, i) => (
        <li key={i} className="q-item">
          <div className="q-text"><SevDot severity={q.severity}></SevDot>{q.q}</div>
          {q.context ? <div className="q-context">{q.context}</div> : null}
        </li>
      ))}
    </ol>
  );
}

function MeetingPrep({ agenda, minutes }) {
  const [showFull, setShowFull] = React.useState(false);
  return (
    <div className="prep-grid">
      <div className="prep-col">
        <h3 className="prep-h">Agenda — next meeting</h3>
        {agenda ? (
          <ul className="agenda-list">
            {agenda.items.slice(0, 18).map((it, i) => <li key={i}>{it}</li>)}
          </ul>
        ) : <div className="empty-note">Drop the agenda .docx to see it here.</div>}
      </div>
      <div className="prep-col">
        <h3 className="prep-h">Motions from last meeting</h3>
        {minutes ? (
          <div>
            <ul className="motion-list">
              {(minutes.motions || []).map((m) => (
                <li key={m.num}><span className="motion-num">{m.num}</span>{m.text}</li>
              ))}
            </ul>
            {minutes.nextMeeting ? <div className="next-meeting">Next meeting: {minutes.nextMeeting}</div> : null}
            <button className="ghost-btn" onClick={() => setShowFull(!showFull)}>
              {showFull ? 'Hide full minutes' : 'Read full minutes'}
            </button>
            {showFull ? (
              <div className="full-minutes">
                {minutes.paras.map((p, i) => <p key={i}>{p}</p>)}
              </div>
            ) : null}
          </div>
        ) : <div className="empty-note">Drop the minutes .docx to see motions here.</div>}
      </div>
    </div>
  );
}

function ArchiveDrawer({ open, archive, onClose }) {
  const docs = [...(archive || [])].sort((a, b) => (b.addedAt || 0) - (a.addedAt || 0));
  const groups = archiveGroups(docs);
  return (
    <div className={'archive-shell' + (open ? ' open' : '')} aria-hidden={!open}>
      <button className="archive-scrim" type="button" onClick={onClose} aria-label="Close archive"></button>
      <aside className="archive-panel" aria-label="Archive">
        <div className="archive-head">
          <div>
            <h2>Archive</h2>
            <div className="archive-sub">{docs.length} imported file{docs.length === 1 ? '' : 's'}</div>
          </div>
          <button className="ghost-btn" onClick={onClose}>Close</button>
        </div>
        {docs.length ? (
          <div className="archive-list">
            {groups.map((group) => (
              <section className="archive-group" key={group.key}>
                <div className="archive-group-head">
                  <h3>{group.label}</h3>
                  <span>{group.docs.length}</span>
                </div>
                <div className="archive-group-files">
                  {group.docs.map((doc) => <ArchiveRow key={doc.id || doc.filename} doc={doc}></ArchiveRow>)}
                </div>
              </section>
            ))}
          </div>
        ) : (
          <div className="archive-empty">
            Drop PDFs or Word files onto the dashboard and they will appear here for meeting reference.
          </div>
        )}
      </aside>
    </div>
  );
}

function archiveGroups(docs) {
  const byKey = new Map();
  for (const doc of docs) {
    const key = doc.monthKey || 'meeting-documents';
    if (!byKey.has(key)) {
      byKey.set(key, {
        key,
        label: doc.monthKey ? monthLong(doc.monthKey) : 'Meeting documents',
        docs: [],
      });
    }
    byKey.get(key).docs.push(doc);
  }
  return [...byKey.values()].sort((a, b) => {
    if (a.key === 'meeting-documents') return 1;
    if (b.key === 'meeting-documents') return -1;
    return b.key.localeCompare(a.key);
  });
}

function ArchiveRow({ doc }) {
  const [url, setUrl] = React.useState(doc.href || null);
  React.useEffect(() => {
    let alive = true;
    if (doc.href) {
      setUrl(doc.href);
      return;
    }
    setUrl(null);
    GKStore.archiveUrl(doc).then((u) => {
      if (!alive) {
        return;
      }
      setUrl(u);
    });
    return () => {
      alive = false;
    };
  }, [doc.id, doc.fileId, doc.href]);
  const month = doc.monthKey ? monthLong(doc.monthKey) : 'Meeting document';
  const added = doc.addedAt ? new Date(doc.addedAt).toLocaleDateString('en-CA', { month: 'short', day: 'numeric', year: 'numeric' }) : '';
  const size = doc.size ? formatBytes(doc.size) : '';
  const action = url ? (
    <div className="archive-actions">
      <a className="archive-open" href={url}>Open</a>
      <a className="archive-download" href={url} download={doc.filename}>Download</a>
    </div>
  ) : (
    <span className="archive-missing">Stored summary only</span>
  );
  return (
    <div className="archive-row">
      <div className="archive-filemark">{doc.fileType || 'FILE'}</div>
      <div className="archive-main">
        <div className="archive-title">{doc.filename}</div>
        <div className="archive-meta">
          <span>{doc.label || doc.kind || 'Document'}</span>
          <span>{month}</span>
          {added ? <span>Added {added}</span> : null}
          {size ? <span>{size}</span> : null}
        </div>
      </div>
      {action}
    </div>
  );
}

function formatBytes(size) {
  if (!size) return '';
  if (size < 1024) return size + ' B';
  if (size < 1024 * 1024) return Math.round(size / 1024) + ' KB';
  return (size / 1024 / 1024).toFixed(1) + ' MB';
}

// ---------- Print one-pager ----------
function PrintSheet({ monthKey, analysis, agenda }) {
  const k = analysis.kpis;
  const top = analysis.flags.attention.slice(0, 6);
  const good = analysis.flags.good.slice(0, 3);
  return (
    <div className="print-sheet">
      <div className="ps-head">
        <div>
          <div className="ps-club">Golf Kenosee Capital Inc.</div>
          <h1 className="ps-title">Board Financial Summary — {monthLong(monthKey)}</h1>
        </div>
        <div className="ps-meta">Prepared from QuickBooks reports · {new Date().toLocaleDateString('en-CA')}</div>
      </div>
      <div className="ps-kpis">
        {[
          { t: monthShort(monthKey) + ' net income', v: k.monthNet, invert: false },
          { t: 'YTD net income', v: k.ytdNet, invert: false },
          { t: monthShort(monthKey) + ' revenue', v: k.monthIncome, invert: false },
          { t: 'Cash & equivalents', v: k.cash, invert: false },
        ].map((x) => (
          <div className="ps-kpi" key={x.t}>
            <div className="ps-kpi-t">{x.t}</div>
            <div className="ps-kpi-v">{fmt(x.v.cur)}</div>
            <div className="ps-kpi-d">{x.v.prior != null ? 'LY ' + fmt(x.v.prior) : ''}</div>
          </div>
        ))}
      </div>
      <div className="ps-cols">
        <div>
          <h2 className="ps-h">Needs a look</h2>
          <table className="ps-table">
            <tbody>
              {top.map((f) => (
                <tr key={f.label + f.scope}>
                  <td><span className={'sev-dot sev-' + f.severity}></span>{f.name} <span className="ps-scope">{f.scope}</span></td>
                  <td className="ps-num">{fmt(f.cur)}</td>
                  <td className="ps-num ps-dim">LY {fmt(f.prior)}</td>
                </tr>
              ))}
            </tbody>
          </table>
          <h2 className="ps-h">Good news</h2>
          <table className="ps-table">
            <tbody>
              {good.map((f) => (
                <tr key={f.label + f.scope}>
                  <td><span className="sev-dot sev-green"></span>{f.name} <span className="ps-scope">{f.scope}</span></td>
                  <td className="ps-num">{fmt(f.cur)}</td>
                  <td className="ps-num ps-dim">LY {fmt(f.prior)}</td>
                </tr>
              ))}
            </tbody>
          </table>
          <h2 className="ps-h">Balance sheet watch</h2>
          <table className="ps-table">
            <tbody>
              {analysis.balanceWatch.map((b) => (
                <tr key={b.name}>
                  <td>{b.name}</td>
                  <td className="ps-num">{fmt(b.cur)}</td>
                  <td className="ps-num ps-dim">{Math.abs(b.diff) < 1 ? 'flat' : (b.diff > 0 ? '+' : '−') + fmt(Math.abs(b.diff))} vs LY</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div>
          <h2 className="ps-h">Questions for the meeting</h2>
          <ol className="ps-questions">
            {analysis.questions.map((q, i) => <li key={i}>{q.q}{q.context ? <span className="ps-ctx"> {q.context}</span> : null}</li>)}
          </ol>
          <h2 className="ps-h">By operation — {monthShort(monthKey)} net</h2>
          <table className="ps-table">
            <tbody>
              {analysis.classes.map((c) => (
                <tr key={c.name}>
                  <td>{c.name}</td>
                  <td className="ps-num">{fmt(c.net)}</td>
                  <td className="ps-num ps-dim">rev {fmt(c.income)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      <div className="ps-foot">Flags: ● red = large swing vs last year · ● amber = notable swing. Figures are unaudited, accrual basis, parsed from the monthly QuickBooks package.</div>
    </div>
  );
}

Object.assign(window, {
  Delta, KpiCard, DrillPanel, SevDot, FlagCard, ClassCard, ClassDrillPanel, BalanceWatch,
  SeasonChart, QuestionsList, MeetingPrep, ArchiveDrawer, PrintSheet,
});
