/* DonorLens — interactive ask-a-question desktop app mockup.
   Exports window.DonorLensApp (the app window) and window.LensMark (brand mark). */
(function () {
  const { useState, useEffect, useRef, useCallback } = React;

  /* ---------------------------------------------------------------- brand mark */
  // Concentric "lens" rings rebuilt as SVG circles so it adapts to any background.
  function LensMark({ size = 34, dim = false }) {
    const rings = dim
      ? ['#c9c4bb', '#bdb8ae', '#b2ada3', '#a7a299', '#9b968d', '#8f8a82']
      : ['#E8255F', '#F6892B', '#3FA34D', '#2C7BE5', '#3B3F8C', '#6C5CE0'];
    const cx = 50, cy = 50;
    return (
      <svg width={size} height={size} viewBox="0 0 100 100" aria-hidden="true" style={{ display: 'block', flex: 'none' }}>
        {rings.map((c, i) => (
          <circle key={i} cx={cx} cy={cy} r={46 - i * 6.6} fill="none" stroke={c} strokeWidth="4.6" />
        ))}
        <circle cx={cx} cy={cy} r={9} fill={dim ? '#6b6760' : '#241f3a'} />
      </svg>
    );
  }
  window.LensMark = LensMark;

  /* ---------------------------------------------------------------- demo data */
  const ANSWERS = {
    lapsed: {
      q: 'Which major donors have lapsed?',
      summary:
        '8 donors who previously gave $5,000+ haven’t made a gift in 18 months or more. Their combined lifetime giving is $612,400 — a meaningful re-engagement opportunity.',
      kind: 'table',
      columns: ['Donor', 'Last gift', 'Amount', 'Lifetime', 'Status'],
      align: [0, 0, 1, 1, 0],
      rows: [
        ['Eleanor V. Hargrove', 'Nov 2023', '$25,000', '$184,500', 'lapsed'],
        ['The Brandt Family Fund', 'Feb 2024', '$15,000', '$142,000', 'lapsed'],
        ['Dr. Priya Raman', 'Sep 2023', '$10,000', '$96,000', 'at risk'],
        ['Coleman & Reyes LLP', 'Jan 2024', '$8,500', '$71,200', 'lapsed'],
        ['Margaret Ovington', 'Dec 2023', '$7,500', '$58,000', 'at risk'],
        ['Theodore Nakamura', 'Oct 2023', '$5,000', '$60,700', 'lapsed'],
      ],
      source: 'Raiser’s Edge · 1,284 constituents scanned · synced 2h ago',
    },
    spring: {
      q: 'How is the spring appeal pacing vs. goal?',
      summary:
        'The spring appeal has raised $148,200 — 74% of your $200,000 goal, and 12% ahead of where last spring stood at this point. Gift count is up, average gift is slightly down.',
      kind: 'pacing',
      goal: 200000,
      raised: 148200,
      lastYear: 132000,
      stats: [
        ['Gifts received', '612', '+9%'],
        ['Average gift', '$242', '−3%'],
        ['New donors', '88', '+21%'],
      ],
      source: 'Raiser’s Edge · appeal “SPR-26” · synced 2h ago',
    },
    upgrades: {
      q: 'Who are my top prospect upgrades?',
      summary:
        '12 current donors show the capacity and engagement to give more. Here are the top 5 by upgrade score — each gives consistently and sits well below estimated capacity.',
      kind: 'table',
      columns: ['Donor', 'Current', 'Est. capacity', 'Score'],
      align: [0, 1, 1, 0],
      rows: [
        ['Walter & Sun-Hi Cho', '$2,500/yr', '$25,000', 'score-94'],
        ['Adaeze Okonkwo', '$1,000/yr', '$15,000', 'score-91'],
        ['The Lindqvist Trust', '$5,000/yr', '$50,000', 'score-88'],
        ['Rosa Delgado', '$1,200/yr', '$10,000', 'score-84'],
        ['Geoffrey Tan', '$750/yr', '$8,000', 'score-79'],
      ],
      source: 'Raiser’s Edge + wealth signals · 1,284 constituents scored',
    },
    board: {
      q: 'Draft the board fundraising summary for Q2.',
      summary: 'Here’s a board-ready draft pulled from your Q2 data. Edit inline, then export to PDF or Docs.',
      kind: 'doc',
      doc: {
        title: 'Q2 FY26 — Fundraising Summary',
        sub: 'Prepared for the Board of Directors · Apr–Jun 2026',
        bullets: [
          ['Total raised', '$486,300 across 1,140 gifts — up 14% over Q2 last year.'],
          ['Spring appeal', '74% to a $200K goal with three weeks remaining; on track to exceed.'],
          ['Major gifts', '6 gifts of $10K+ closed, including a $25K renewal from a lapsed donor re-engaged this quarter.'],
          ['Donor retention', 'Overall retention holding at 68%; first-year retention improved 4 points to 41%.'],
          ['Watch items', '8 lapsed major donors flagged for personal outreach before fiscal year-end.'],
        ],
      },
      source: 'Generated from Raiser’s Edge · Q2 FY26 · review before sending',
    },
  };
  const ORDER = ['lapsed', 'spring', 'upgrades', 'board'];

  /* ---------------------------------------------------------------- bits */
  function Badge({ label }) {
    const at = label === 'at risk';
    return (
      <span className={'dl-badge ' + (at ? 'dl-badge--warn' : 'dl-badge--lapsed')}>
        <span className="dl-badge-dot" />
        {label}
      </span>
    );
  }
  function ScorePill({ value }) {
    const n = parseInt(value.replace('score-', ''), 10);
    return (
      <span className="dl-score">
        <span className="dl-score-bar"><span className="dl-score-fill" style={{ width: n + '%' }} /></span>
        <span className="dl-score-num">{n}</span>
      </span>
    );
  }

  function AnswerTable({ a }) {
    return (
      <div className="dl-tablewrap">
        <table className="dl-table">
          <thead>
            <tr>{a.columns.map((c, i) => <th key={i} className={a.align[i] ? 'r' : ''}>{c}</th>)}</tr>
          </thead>
          <tbody>
            {a.rows.map((row, ri) => (
              <tr key={ri}>
                {row.map((cell, ci) => {
                  const cls = a.align[ci] ? 'r' : '';
                  if (ci === 0) return <td key={ci} className={cls + ' dl-name'}>{cell}</td>;
                  if (a.kind === 'table' && (cell === 'lapsed' || cell === 'at risk'))
                    return <td key={ci} className={cls}><Badge label={cell} /></td>;
                  if (typeof cell === 'string' && cell.startsWith('score-'))
                    return <td key={ci} className={cls}><ScorePill value={cell} /></td>;
                  return <td key={ci} className={cls}>{cell}</td>;
                })}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    );
  }

  function AnswerPacing({ a }) {
    const pct = Math.round((a.raised / a.goal) * 100);
    const lyPct = Math.round((a.lastYear / a.goal) * 100);
    const fmt = (n) => '$' + (n / 1000).toFixed(1).replace('.0', '') + 'K';
    return (
      <div className="dl-pacing">
        <div className="dl-pacing-head">
          <div><span className="dl-big">{fmt(a.raised)}</span><span className="dl-of">of {fmt(a.goal)} goal</span></div>
          <div className="dl-pct">{pct}%</div>
        </div>
        <div className="dl-bar">
          <div className="dl-bar-ly" style={{ width: lyPct + '%' }} title="Last year" />
          <div className="dl-bar-fill" style={{ width: pct + '%' }} />
        </div>
        <div className="dl-bar-legend">
          <span><i className="dot fill" /> This year</span>
          <span><i className="dot ly" /> Last year, same date ({fmt(a.lastYear)})</span>
        </div>
        <div className="dl-statrow">
          {a.stats.map((s, i) => (
            <div className="dl-stat" key={i}>
              <div className="dl-stat-label">{s[0]}</div>
              <div className="dl-stat-val">{s[1]} <span className={'dl-delta ' + (s[2][0] === '+' ? 'up' : 'down')}>{s[2]}</span></div>
            </div>
          ))}
        </div>
      </div>
    );
  }

  function AnswerDoc({ a }) {
    const d = a.doc;
    return (
      <div className="dl-doc">
        <div className="dl-doc-title">{d.title}</div>
        <div className="dl-doc-sub">{d.sub}</div>
        <div className="dl-doc-body">
          {d.bullets.map((b, i) => (
            <div className="dl-doc-line" key={i}>
              <div className="dl-doc-k">{b[0]}</div>
              <div className="dl-doc-v">{b[1]}</div>
            </div>
          ))}
        </div>
        <div className="dl-doc-actions">
          <span className="dl-chip-ghost">Export PDF</span>
          <span className="dl-chip-ghost">Copy to Docs</span>
        </div>
      </div>
    );
  }

  function Answer({ a }) {
    return (
      <div className="dl-answer">
        <div className="dl-answer-head">
          <LensMark size={22} />
          <span>DonorLens</span>
        </div>
        <p className="dl-summary">{a.summary}</p>
        {a.kind === 'table' && <AnswerTable a={a} />}
        {a.kind === 'pacing' && <AnswerPacing a={a} />}
        {a.kind === 'doc' && <AnswerDoc a={a} />}
        <div className="dl-source"><span className="dl-source-dot" />{a.source}</div>
      </div>
    );
  }

  function Thinking() {
    return (
      <div className="dl-answer dl-thinking">
        <div className="dl-answer-head"><LensMark size={22} /><span>DonorLens</span></div>
        <div className="dl-think-row"><span className="dl-think-pulse" />Reading your database…</div>
        <div className="dl-skel s1" /><div className="dl-skel s2" /><div className="dl-skel s3" />
      </div>
    );
  }

  /* ---------------------------------------------------------------- app */
  function DonorLensApp({ variant = 'full', startKey = 'lapsed' }) {
    const [activeKey, setActiveKey] = useState(startKey);
    const [phase, setPhase] = useState('answer'); // 'thinking' | 'answer'
    const [typed, setTyped] = useState('');
    const scrollRef = useRef(null);
    const timer = useRef(null);

    const ask = useCallback((key) => {
      if (!ANSWERS[key]) return;
      clearTimeout(timer.current);
      setActiveKey(key);
      setTyped('');
      setPhase('thinking');
      timer.current = setTimeout(() => setPhase('answer'), 900);
    }, []);

    useEffect(() => () => clearTimeout(timer.current), []);

    useEffect(() => {
      if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }, [phase, activeKey]);

    // failsafe: once entrance animations have played, drop them so answer/chart bars
    // rest on their final visible state even where the animation clock is throttled.
    useEffect(() => {
      if (phase !== 'answer') return;
      const t = setTimeout(() => {
        if (!scrollRef.current) return;
        scrollRef.current.querySelectorAll('.dl-answer, .dl-bar-fill').forEach((el) => { el.style.animation = 'none'; });
      }, 520);
      return () => clearTimeout(t);
    }, [phase, activeKey]);

    const a = ANSWERS[activeKey];
    const suggestions = ORDER.filter((k) => k !== activeKey).slice(0, 3);

    const submit = (e) => {
      e.preventDefault();
      const v = typed.trim().toLowerCase();
      if (!v) return;
      let key = 'lapsed';
      if (v.includes('pac') || v.includes('appeal') || v.includes('goal')) key = 'spring';
      else if (v.includes('upgrade') || v.includes('prospect') || v.includes('more')) key = 'upgrades';
      else if (v.includes('board') || v.includes('summary') || v.includes('report') || v.includes('draft')) key = 'board';
      else if (v.includes('laps') || v.includes('major') || v.includes('lost')) key = 'lapsed';
      ask(key);
    };

    return (
      <div className={'dl-app dl-app--' + variant}>
        <div className="dl-titlebar">
          <div className="dl-lights"><i /><i /><i /></div>
          <div className="dl-titlebar-name"><LensMark size={16} /> DonorLens</div>
          <div className="dl-conn"><span className="dl-conn-dot" />Raiser’s Edge · local</div>
        </div>

        <div className="dl-canvas" ref={scrollRef}>
          <div className="dl-bubble">{a.q}</div>
          {phase === 'thinking' ? <Thinking /> : <Answer a={a} />}
        </div>

        <div className="dl-composer">
          <div className="dl-suggests">
            {suggestions.map((k) => (
              <button key={k} className="dl-chip" onClick={() => ask(k)} type="button">{ANSWERS[k].q}</button>
            ))}
          </div>
          <form className="dl-inputbar" onSubmit={submit}>
            <span className="dl-input-spark"><LensMark size={18} /></span>
            <input
              className="dl-input"
              value={typed}
              onChange={(e) => setTyped(e.target.value)}
              placeholder="Ask anything about your donors…"
              aria-label="Ask a question about your donors"
            />
            <button className="dl-send" type="submit" aria-label="Ask">Ask</button>
          </form>
        </div>
      </div>
    );
  }

  window.DonorLensApp = DonorLensApp;
})();
