/* Page: Weekly report (Amendment No. 1, Appendix C) — the seven-item weekly
   metrics snapshot the Monday job stores (api/jobs/run-weekly-report.js),
   plus the qualified-page maintenance tracker (Amendment Appendix A, clauses
   5.1-5.6) and a history of prior weeks. Client-visible by design (clause
   3.1); the item-7 note editor and the qualified-page month-end verification
   form are agency-role only (design spec section 4b/5:
   docs/stlaf-reporting-refinements-design-2026-07-05.md). Config-gated: the
   Sidebar only lists this route when client.reporting.weekly.enabled — STLAF
   today, no other client. */
const { useState: useStateWk } = React;

function wkPctDelta(now, prev) {
  if (!prev) return null;
  return Math.round(((now - prev) / prev) * 100);
}

// Native KPI tile matching the shared .kpi markup (span.label/.value/.delta/
// .source — see RankingsView.jsx) rather than window.KPI, whose delta lines
// are hardcoded to "prev mo"/"prev yr" and don't fit a 7-day-vs-prior-7-day
// weekly comparison.
function WeeklyStat({ label, value, prev, source }) {
  const d = wkPctDelta(value, prev);
  const cls = d == null || d === 0 ? 'flat' : d > 0 ? 'up' : 'down';
  return (
    <div className="kpi">
      <span className="label">{label}</span>
      <span className="value">{Number(value || 0).toLocaleString()}</span>
      <span className={`delta ${cls}`}>
        {d != null && d !== 0 && <Icon name={d > 0 ? 'arrowUp' : 'arrowDown'} size={10}/>}
        {d != null ? `${d > 0 ? '+' : ''}${d}% vs prior week` : 'vs prior week'}
      </span>
      {source && <span className="source">{source}</span>}
    </div>
  );
}

// One qualified-page row. Fee is shown to every role (the client signs the
// fee schedule); the Verify control (position/tier/note) is agency-only,
// enforced again server-side by the route's agencyOnly guard.
function QualifiedPageRow({ client, q, month, isAgency, onVerified }) {
  const [editing, setEditing] = useStateWk(false);
  const [tier, setTier] = useStateWk(q.manual?.tier || 'page1');
  const [position, setPosition] = useStateWk(q.manual?.position ?? '');
  const [note, setNote] = useStateWk('');
  const [saving, setSaving] = useStateWk(false);
  const [err, setErr] = useStateWk(null);
  const field = { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 4, padding: '4px 6px', color: 'var(--text)', fontSize: 12, width: '100%' };

  const status = q.manual?.tier
    ? `Verified ${q.manual.tier === 'top3' ? 'Top 3' : q.manual.tier === 'page1' ? 'Page 1' : 'not qualified'}`
    : q.qualifiedAuto ? 'Qualified, month-end check pending'
    : q.onTrack ? 'On track' : 'Not on track';

  const confirmedFee = q.manual?.tier ? q.feePhp : null;
  const feeLabel = confirmedFee != null
    ? `₱${confirmedFee.toLocaleString()}`
    : q.projectedFeePhp ? `₱${q.projectedFeePhp.toLocaleString()} (projected)` : '—';

  const save = () => {
    setSaving(true); setErr(null);
    window.apiSend(`/api/clients/${client.id}/qualified-months/verify`, 'POST', {
      pageKey: q.key, month, tier,
      position: position === '' ? null : Number(position),
      note: note.trim() || null,
    }).then(() => { setEditing(false); setNote(''); if (onVerified) onVerified(); })
      .catch(e => setErr(e.message)).finally(() => setSaving(false));
  };

  return (
    <tr>
      <td>{q.page}</td>
      <td className="num mono">{q.autoDaysTop10}/15</td>
      <td>{status}{q.overCap && <span className="serp-badge" style={{marginLeft: 6}}>Over cap</span>}</td>
      <td className="num mono">{feeLabel}</td>
      {isAgency && (
        <td>
          {!editing ? (
            <button className="btn btn-ghost" style={{padding: '3px 10px', fontSize: 11}} onClick={() => setEditing(true)}>Verify</button>
          ) : (
            <div style={{display: 'flex', flexDirection: 'column', gap: 4, minWidth: 170}}>
              <select value={tier} onChange={e => setTier(e.target.value)} style={field}>
                <option value="top3">Top 3</option>
                <option value="page1">Page 1</option>
                <option value="none">Not qualified</option>
              </select>
              <input type="number" placeholder="Position" value={position} onChange={e => setPosition(e.target.value)} style={field}/>
              <input type="text" placeholder="Note (optional)" value={note} onChange={e => setNote(e.target.value)} style={field}/>
              <div style={{display: 'flex', gap: 6}}>
                <button className="btn btn-secondary" style={{padding: '3px 10px', fontSize: 11}} disabled={saving} onClick={save}>{saving ? 'Saving...' : 'Save'}</button>
                <button className="btn btn-ghost" style={{padding: '3px 10px', fontSize: 11}} onClick={() => setEditing(false)}>Cancel</button>
              </div>
              {err && <div className="error-state" style={{fontSize: 11}}>{err}</div>}
            </div>
          )}
        </td>
      )}
    </tr>
  );
}

// CSV export button (promised to STLAF 2026-07-13 so they can attach the figures
// to an internal payment request). Client-visible: the client is the one who
// needs the file. Errors surface inline — a silent no-op on a download the user
// is waiting for is worse than an ugly message.
function ExportCsvButton({ client, dataset, month, label }) {
  const [busy, setBusy] = useStateWk(false);
  const [err, setErr] = useStateWk(null);

  const go = () => {
    setBusy(true); setErr(null);
    const qs = `dataset=${encodeURIComponent(dataset)}` + (month ? `&month=${encodeURIComponent(month)}` : '');
    window.downloadFile(`/api/clients/${client.id}/export.csv?${qs}`, `${client.id}-${dataset}.csv`)
      .catch(e => setErr(e.message))
      .finally(() => setBusy(false));
  };

  return (
    <>
      <button className="btn btn-ghost" style={{padding: '3px 10px', fontSize: 11}} disabled={busy} onClick={go}>
        {busy ? 'Preparing...' : (label || 'Export CSV')}
      </button>
      {err && <span className="error-state" style={{fontSize: 11, marginLeft: 8}}>{err}</span>}
    </>
  );
}

function WeeklyView({ client }) {
  const [version, setVersion] = useStateWk(0);
  const { data, loading, error } = useApi(`/api/clients/${client.id}/weekly`, [client.id, version]);
  const [noteDraft, setNoteDraft] = useStateWk(null);
  const [savingNote, setSavingNote] = useStateWk(false);
  const [noteErr, setNoteErr] = useStateWk(null);
  // window.__GE_USER__ is set from App()'s `me` state (index.html) — the
  // established convention (see TicketsView.jsx, RoadmapView.jsx) rather than
  // a `me` prop, which no view in this app currently receives.
  const me = window.__GE_USER__;
  const isAgency = !me || me.role === 'agency';
  const field = { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 4, padding: '6px 8px', color: 'var(--text)', fontSize: 13, width: '100%' };

  if (loading) return <div className="loading-state">Loading weekly reports...</div>;
  if (error) return <div className="error-state">Failed to load weekly data: {error}</div>;

  const D = data || {};
  const snaps = D.snapshots || [];
  const latest = snaps[0];

  const saveNote = () => {
    setSavingNote(true); setNoteErr(null);
    window.apiSend(`/api/clients/${client.id}/weekly/note`, 'PUT', { note: noteDraft })
      .then(() => { setNoteDraft(null); setVersion(v => v + 1); })
      .catch(e => setNoteErr(e.message)).finally(() => setSavingNote(false));
  };

  if (!latest) {
    return (
      <div className="page-head"><div>
        <div className="eyebrow gold"><span className="dot"/>Weekly report</div>
        <h1>Weekly report</h1>
        <div className="sub">No weekly snapshots yet. The first Monday run creates one.</div>
      </div></div>
    );
  }

  const p = latest.payload || {};
  const month = p.window?.month || String(latest.week_start || '').slice(0, 7);
  const moversUp = p.rankings?.moversUp || [];
  const moversDown = p.rankings?.moversDown || [];
  const qualified = p.qualifiedPages || [];

  return (
    <>
      <div className="page-head"><div>
        <div className="eyebrow gold"><span className="dot"/>Weekly report · week of {latest.week_start}</div>
        <h1>Weekly report</h1>
        <div className="sub">The seven Appendix C metrics, refreshed every Monday per our reporting arrangement.</div>
      </div></div>

      <div className="kpi-grid" style={{gridTemplateColumns: 'repeat(6, 1fr)'}}>
        <WeeklyStat label="Search clicks · 7d" value={p.gsc?.clicks} prev={p.gsc?.prevClicks} source="Search Console"/>
        <WeeklyStat label="Impressions · 7d" value={p.gsc?.impressions} prev={p.gsc?.prevImpressions} source="Search Console"/>
        <div className="kpi">
          <span className="label">Keywords in Top 10</span>
          <span className="value">{p.rankings?.top10 || 0}</span>
          <span className="delta flat">{moversUp.length} up · {moversDown.length} down</span>
          <span className="source">this week</span>
        </div>
        <div className="kpi">
          <span className="label">Keywords in Top 3</span>
          <span className="value">{p.rankings?.top3 || 0}</span>
          <span className="delta flat">of {p.rankings?.top10 || 0} in Top 10</span>
          <span className="source">this week</span>
        </div>
        <WeeklyStat label="Organic sessions · 7d" value={p.sessions?.organic} prev={p.sessions?.prevOrganic} source="GA4"/>
        <WeeklyStat label="Lead inquiries · 7d" value={p.inquiries?.total} prev={p.inquiries?.prevTotal} source="GA4 Key Events"/>
      </div>

      <div className="row-2" style={{marginTop: 24}}>
        <div className="panel">
          <div className="panel-head">
            <h3>Qualified pages</h3>
            <div style={{display: 'flex', alignItems: 'center', gap: 8}}>
              <span className="sub">Top 10 for 15+ days this month · {month}</span>
              <ExportCsvButton client={client} dataset="qualified-pages" month={month} label="Export CSV"/>
            </div>
          </div>
          <div className="panel-body" style={{padding: 0}}>
            <table className="table">
              <thead>
                <tr>
                  <th>Page</th><th className="num">Days in Top 10</th><th>Status</th><th className="num">Fee</th>
                  {isAgency && <th>Verify</th>}
                </tr>
              </thead>
              <tbody>
                {qualified.map((q, i) => (
                  <QualifiedPageRow key={q.key || i} client={client} q={q} month={month} isAgency={isAgency}
                                     onVerified={() => setVersion(v => v + 1)}/>
                ))}
                {qualified.length === 0 && (
                  <tr><td colSpan={isAgency ? 5 : 4} className="dim" style={{fontSize: 12, padding: '10px 18px'}}>No qualified pages configured.</td></tr>
                )}
              </tbody>
            </table>
          </div>
          {isAgency && qualified.length > 0 && (
            <div className="panel-body" style={{paddingTop: 0}}>
              <div className="dim" style={{fontSize: 11}}>Saved verifications update the invoice record immediately and appear in snapshots generated after entry. Enter month-end verifications before the first Monday noon run of the new month.</div>
            </div>
          )}
        </div>

        <div className="panel">
          <div className="panel-head"><h3>Movers</h3><span className="sub">vs 7 days earlier</span></div>
          <div className="panel-body">
            {moversUp.length === 0 && moversDown.length === 0
              ? <div className="dim" style={{fontSize: 12}}>No material movers this week.</div>
              : <ul style={{listStyle: 'none', margin: 0, padding: 0, fontSize: 13}}>
                  {moversUp.map((m, i) => <li key={'u' + i}>▲ {m.keyword}: {m.from} → {m.to}</li>)}
                  {moversDown.map((m, i) => <li key={'d' + i}>▼ {m.keyword}: {m.from} → {m.to}</li>)}
                </ul>}
            <div style={{marginTop: 12, fontSize: 13}}>
              {p.aeo
                ? <>AI visibility: <strong>{p.aeo.visibilityBlended}%</strong> of {p.aeo.promptCount} watched prompts · share of voice {p.aeo.shareOfVoiceBrandPct}%</>
                : 'AI visibility capture pending this week.'}
            </div>
          </div>
        </div>
      </div>

      <div className="panel" style={{marginTop: 16}}>
        <div className="panel-head"><h3>Work in progress</h3><span className="sub">Active roadmap milestones + agency notes</span></div>
        <div className="panel-body">
          {(p.workItems || []).length === 0
            ? <div className="dim" style={{fontSize: 12}}>No open build items this week.</div>
            : <ul style={{fontSize: 13, margin: 0, paddingLeft: 18}}>
                {(p.workItems || []).map((w, i) => <li key={i}>{w.title}{w.targetDate ? ` (target ${w.targetDate})` : ''}</li>)}
              </ul>}
          {p.note && <p style={{fontSize: 13, marginTop: 10, color: 'var(--text-dim)'}}>{p.note}</p>}

          {isAgency && (
            <div style={{marginTop: 14, paddingTop: 14, borderTop: '1px solid var(--border-light)'}}>
              <div className="mono-label" style={{marginBottom: 8}}>Note for next Monday's report</div>
              {noteDraft === null ? (
                <button className="btn btn-secondary" onClick={() => setNoteDraft(D.note || '')}>Edit note</button>
              ) : (
                <>
                  <textarea value={noteDraft} onChange={e => setNoteDraft(e.target.value)} rows={3} style={{...field, resize: 'vertical'}}/>
                  <div style={{display: 'flex', gap: 8, marginTop: 8}}>
                    <button className="btn btn-secondary" disabled={savingNote} onClick={saveNote}>{savingNote ? 'Saving...' : 'Save note'}</button>
                    <button className="btn btn-ghost" onClick={() => setNoteDraft(null)}>Cancel</button>
                  </div>
                  {noteErr && <div className="error-state" style={{marginTop: 6}}>{noteErr}</div>}
                </>
              )}
            </div>
          )}
        </div>
      </div>

      <div className="panel" style={{marginTop: 16}}>
        <div className="panel-head">
          <h3>Past weeks</h3>
          <ExportCsvButton client={client} dataset="weekly" label="Export CSV"/>
        </div>
        <div className="panel-body" style={{padding: 0}}>
          <table className="table">
            <thead><tr><th>Week of</th><th className="num">Clicks</th><th className="num">Sessions</th><th className="num">Top 10</th><th className="num">Inquiries</th></tr></thead>
            <tbody>
              {snaps.map((s, i) => (
                <tr key={i}>
                  <td className="mono">{s.week_start}</td>
                  <td className="num mono">{s.payload?.gsc?.clicks ?? 0}</td>
                  <td className="num mono">{s.payload?.sessions?.organic ?? 0}</td>
                  <td className="num mono">{s.payload?.rankings?.top10 ?? 0}</td>
                  <td className="num mono">{s.payload?.inquiries?.total ?? 0}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
}
window.WeeklyView = WeeklyView;
