/* global React */
// Product preview — a queue you can actually clear, with outcome stats.

// Counts from 0 to `target` over `duration` ms.
// Phase 1 (0–65% of time): linear to 90% of value — fast, satisfying climb.
// Phase 2 (65–100% of time): ease-out cubic over the last 10% — each final digit
// takes noticeably longer than the previous, landing with a deliberate settle.
function useCountUp(target, duration, active) {
  var _val = React.useState(0);
  var value = _val[0]; var setValue = _val[1];
  var raf = React.useRef(null);
  var t0  = React.useRef(null);

  React.useEffect(() => {
    if (!active) return;
    t0.current = null;

    const easeOutExpo = (p) => {
      if (p >= 1) return 1;
      return 1 - Math.pow(2, -10 * p); // rapid early gain, then asymptotes hard toward 1
    };

    const step = (ts) => {
      if (t0.current === null) t0.current = ts;
      const p = Math.min((ts - t0.current) / duration, 1);
      setValue(Math.round(easeOutExpo(p) * target));
      if (p < 1) raf.current = requestAnimationFrame(step);
      else setValue(target);
    };

    raf.current = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf.current);
  }, [active]);

  return value;
}

function StatFigure({ num, suffix = '', active }) {
  const v = useCountUp(num, 3000, active);
  return <>{v}{suffix}</>;
}

function ProductPreview() {
  const DS = window.ReconcileAIDesignSystem_c7572b;
  const { ExceptionCard } = DS;

  const POOL = [
    { poolId: 0, merchant: 'Figma Inc.', amount: '£540.00', date: '2026-06-02 · 16:40', reason: 'Recurring annual charge matching last year\'s design-tool subscription. Same merchant, same amount — high confidence.', suggestedAccount: 'Software & hosting', confidence: 98, pastTransactions: [{ date: '2025-06-02', amount: '£540.00' }, { date: '2024-06-03', amount: '£480.00' }] },
    { poolId: 1, merchant: 'Pret A Manger', amount: '£42.18', date: '2026-06-01 · 12:55', reason: 'Small card payment during a working day, consistent with team lunches you usually book to staff entertainment.', suggestedAccount: 'Staff & entertainment', confidence: 89 },
    { poolId: 2, merchant: 'Slack Technologies', amount: '£216.00', date: '2026-05-31 · 09:00', reason: 'Monthly team communication subscription. Matches seat count invoice from last month\'s renewal — same billing cycle.', suggestedAccount: 'Software & hosting', confidence: 95, pastTransactions: [{ date: '2026-04-30', amount: '£216.00' }, { date: '2026-03-31', amount: '£216.00' }, { date: '2026-02-28', amount: '£192.00' }] },
    { poolId: 3, merchant: 'British Gas Business', amount: '£389.44', date: '2026-05-29 · 17:20', reason: 'Quarterly utility bill for your office. Consistent with previous quarter and aligns with seasonal usage patterns.', suggestedAccount: 'Utilities', confidence: 88, pastTransactions: [{ date: '2026-02-27', amount: '£412.80' }, { date: '2025-11-29', amount: '£356.20' }] },
    { poolId: 4, merchant: 'Adobe Creative Cloud', amount: '£119.98', date: '2026-05-28 · 08:45', reason: 'Monthly creative suite licence for two seats. Amount and cadence match your existing Adobe subscription exactly.', suggestedAccount: 'Software & hosting', confidence: 97, pastTransactions: [{ date: '2026-04-28', amount: '£119.98' }, { date: '2026-03-28', amount: '£119.98' }] },
    { poolId: 5, merchant: 'Deliveroo for Business', amount: '£76.40', date: '2026-05-27 · 13:10', reason: 'Lunchtime group order placed via your corporate Deliveroo account during an all-hands meeting day.', suggestedAccount: 'Staff & entertainment', confidence: 86 },
    { poolId: 6, merchant: 'Royal Mail Business', amount: '£234.00', date: '2026-05-26 · 10:20', reason: 'Bulk postage charge consistent with your end-of-month client invoice mailings. Same supplier and similar amount as April.', suggestedAccount: 'Postage & shipping', confidence: 91, pastTransactions: [{ date: '2026-04-30', amount: '£218.50' }, { date: '2026-03-31', amount: '£241.00' }] },
  ];

  const poolCursorRef = React.useRef(2);
  const uidCursorRef  = React.useRef(100);
  const statsRef      = React.useRef(null);
  const [statsActive, setStatsActive] = React.useState(false);

  const [items, setItems] = React.useState([
    { uid: 100, poolId: 0, state: 'visible' },
    { uid: 101, poolId: 1, state: 'visible' },
  ]);

  React.useEffect(() => {
    uidCursorRef.current = 101;
  }, []);

  React.useEffect(() => { requestAnimationFrame(() => window.lucide && window.lucide.createIcons()); });

  React.useEffect(() => {
    const el = statsRef.current;
    if (!el) return;
    if (!window.IntersectionObserver) { setStatsActive(true); return; }
    const io = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) { setStatsActive(true); io.disconnect(); } },
      { threshold: 0.5 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);

  const handleResolve = (uid) => {
    // 1. start exit animation on the resolved card
    setItems(prev => prev.map(it => it.uid === uid ? { ...it, state: 'exiting' } : it));

    // 2. after exit, swap it out and bring next card in from the pool
    setTimeout(() => {
      const nextPoolId = poolCursorRef.current % POOL.length;
      poolCursorRef.current += 1;
      uidCursorRef.current += 1;
      const newItem = { uid: uidCursorRef.current, poolId: nextPoolId, state: 'entering' };

      setItems(prev => {
        const without = prev.filter(it => it.uid !== uid);
        return [...without, newItem];
      });
    }, 400);
  };

  const stats = [
    { num: 312, suffix: '',     label: 'exceptions cleared this month' },
    { num: 96,  suffix: '%',    label: 'auto-categorised, zero touch' },
    { num: 8,   suffix: ' hrs', label: 'saved per month, on average' },
  ];

  return (
    <section id="exceptions-queue" style={{ maxWidth: 'var(--container-max)', margin: '0 auto', padding: 'var(--section-y) var(--container-pad)' }}>
      <style>{`
        @keyframes ppExit {
          from { opacity: 1; transform: translateY(0)   scale(1);    }
          to   { opacity: 0; transform: translateY(-12px) scale(0.97); }
        }
        @keyframes ppEnter {
          from { opacity: 0; transform: translateY(16px) scale(0.97); }
          to   { opacity: 1; transform: translateY(0)   scale(1);    }
        }
        .pp-exiting  { animation: ppExit  0.38s cubic-bezier(.4,0,.6,1) forwards; pointer-events: none; }
        .pp-entering { animation: ppEnter 0.45s cubic-bezier(.22,.68,0,1.15) forwards; }
      `}</style>

      <div style={{ display: 'grid', gridTemplateColumns: '0.92fr 1.08fr', gap: 'clamp(2rem,5vw,4.5rem)', alignItems: 'center' }} className="rai-preview-grid">
        <div style={{ display: 'flex', flexDirection: 'column', gap: '22px' }}>
          <span className="ds-eyebrow">Impact</span>
          <h2 style={{ fontSize: 'clamp(1.9rem,3.4vw,2.6rem)', fontWeight: 700, letterSpacing: '-0.025em', color: 'var(--ink-900)' }}>
            A queue you can actually clear.
          </h2>
          <p style={{ fontSize: '17px', lineHeight: 1.6, color: 'var(--text-muted)', margin: 0, maxWidth: '40ch' }}>
            No more spreadsheets of mystery line items. Each exception arrives explained, with the
            account already chosen — so clearing the backlog feels less like detective work and
            more like saying yes.
          </p>
          <div ref={statsRef} style={{ display: 'flex', gap: '28px', flexWrap: 'wrap', marginTop: '4px' }}>
            {stats.map((s) => (
              <div key={s.label} style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
                <span style={{ fontFamily: 'var(--font-mono)', fontSize: '30px', fontWeight: 600, color: 'var(--ink-900)', letterSpacing: '-0.02em' }}>
                  <StatFigure num={s.num} suffix={s.suffix} active={statsActive} />
                </span>
                <span style={{ fontSize: '13px', color: 'var(--text-muted)', maxWidth: '18ch' }}>{s.label}</span>
              </div>
            ))}
          </div>
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: '14px' }}>
          {items.map(item => {
            const card = POOL[item.poolId];
            const cls = item.state === 'exiting' ? 'pp-exiting' : item.state === 'entering' ? 'pp-entering' : '';
            return (
              <div key={item.uid} className={cls}>
                <ExceptionCard
                  {...card}
                  onResolve={() => handleResolve(item.uid)}
                />
              </div>
            );
          })}
        </div>
      </div>
    </section>
  );
}
window.ProductPreview = ProductPreview;
