/* cst-purchase.jsx — micro-purchase UX. SlideToBuy (a Whatnot-style slide-to-pay
   confirm control) + FactorDetail (the tappable radar-point info card).
   Exported to window. Demo purchases persist per-result in localStorage. */

const { useState: _puS2, useRef: _puR2, useEffect: _puE2 } = React;
const _PUC = window.CST;
const { FONT: _puF, TEXT: _puT, HAZE: _puH, HAZE_DIM: _puHD, HAIR: _puHR, GLASS: _puG, INK: _puI, INK_DEEP: _puID } = _PUC;

// slide-to-pay: drag the thumb to the end to confirm a purchase
function SlideToBuy({ label = 'Slide to pay', price = '99¢', accent = '#FFB454', onConfirm }) {
  const trackRef = _puR2(null);
  const [x, setX] = _puS2(0);          // thumb offset px
  const [done, setDone] = _puS2(false);
  const drag = _puR2(false);
  const geom = _puR2({ w: 0, thumb: 56 });

  const measure = () => {
    const el = trackRef.current; if (!el) return;
    geom.current.w = el.clientWidth;
  };
  _puE2(() => { measure(); window.addEventListener('resize', measure); return () => window.removeEventListener('resize', measure); }, []);

  const maxX = () => Math.max(0, geom.current.w - geom.current.thumb - 8);
  const onDown = (e) => { if (done) return; drag.current = true; e.currentTarget.setPointerCapture && e.currentTarget.setPointerCapture(e.pointerId); };
  const onMove = (e) => {
    if (!drag.current || done) return;
    const rect = trackRef.current.getBoundingClientRect();
    const px = Math.min(maxX(), Math.max(0, e.clientX - rect.left - geom.current.thumb / 2));
    setX(px);
  };
  const finish = () => {
    if (!drag.current || done) return;
    drag.current = false;
    if (x >= maxX() - 6) {
      setX(maxX()); setDone(true);
      setTimeout(() => onConfirm && onConfirm(), 420);
    } else {
      setX(0); // snap back
    }
  };
  const pct = maxX() > 0 ? x / maxX() : 0;

  return (
    <div ref={trackRef} onPointerMove={onMove} onPointerUp={finish} onPointerCancel={finish}
      style={{
        position: 'relative', height: 56, borderRadius: 14, overflow: 'hidden', touchAction: 'none',
        background: _puID, border: `1px solid ${done ? accent : _puHR}`, userSelect: 'none',
      }}>
      {/* fill trail */}
      <div style={{ position: 'absolute', inset: 0, width: x + 56, background: accent + '22', transition: drag.current ? 'none' : 'width .25s' }} />
      {/* label */}
      <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, pointerEvents: 'none' }}>
        <span style={{ fontFamily: _puF, fontSize: 13.5, fontWeight: 700, color: done ? accent : _puH, opacity: done ? 1 : 1 - pct * 0.7, letterSpacing: 0.3 }}>
          {done ? '✓ Unlocked — preparing report…' : `${label} ${price}  ›››`}
        </span>
      </div>
      {/* thumb */}
      <div onPointerDown={onDown} style={{
        position: 'absolute', top: 4, left: 4, width: 48, height: 48, borderRadius: 11, cursor: done ? 'default' : 'grab',
        transform: `translateX(${x}px)`, transition: drag.current ? 'none' : 'transform .25s',
        background: accent, display: 'flex', alignItems: 'center', justifyContent: 'center',
        boxShadow: `0 4px 14px -4px ${accent}`,
      }}>
        <span style={{ color: _puI, fontSize: 19, fontWeight: 800 }}>{done ? '✓' : '→'}</span>
      </div>
    </div>);
}

// tappable radar-point detail card (shown over the verdict)
function FactorDetail({ factor, accent, onClose }) {
  if (!factor) return null;
  const sc = factor.read.band === 'strong' ? '#5FD08C' : factor.read.band === 'solid' ? accent : factor.read.band === 'shaky' ? '#FFC861' : '#FF7E6E';
  return (
    <div onClick={onClose} style={{ position: 'absolute', inset: 0, zIndex: 20, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 26, background: 'rgba(7,9,12,0.55)', backdropFilter: 'blur(4px)', WebkitBackdropFilter: 'blur(4px)', animation: 'cstFadeIn .18s ease' }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: '100%', maxWidth: 320, background: 'linear-gradient(180deg, #14171D, #0F1115)', border: `1px solid ${accent}44`,
        borderRadius: 16, padding: 18, boxShadow: '0 18px 50px -18px rgba(0,0,0,0.8)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontFamily: _puF, fontWeight: 800, fontSize: 16, color: _puT }}>{factor.label}</span>
            <span style={{ fontFamily: _puF, fontWeight: 800, fontSize: 15, color: sc }}>{factor.score}<span style={{ fontSize: 10, color: _puHD }}>/100</span></span>
          </div>
          <button onClick={onClose} style={{ cursor: 'pointer', width: 28, height: 28, borderRadius: 8, background: _puG, border: `1px solid ${_puHR}`, color: _puH, fontSize: 13 }}>✕</button>
        </div>
        <div style={{ height: 5, borderRadius: 99, background: 'rgba(236,237,241,0.1)', overflow: 'hidden', marginBottom: 12 }}>
          <div style={{ width: factor.score + '%', height: '100%', background: sc, boxShadow: `0 0 8px ${sc}` }} />
        </div>
        <p style={{ margin: '0 0 9px', fontFamily: _puF, fontSize: 11.5, lineHeight: 1.5, color: _puH }}>{factor.measures}</p>
        <p style={{ margin: 0, fontFamily: _puF, fontSize: 13, lineHeight: 1.5, color: _puT, fontWeight: 600 }}>{factor.read.text}</p>
      </div>
    </div>);
}

// generic tappable detail for non-score values (price bars, readiness, etc.)
function InfoCard({ info, accent, onClose }) {
  if (!info) return null;
  return (
    <div onClick={onClose} style={{ position: 'absolute', inset: 0, zIndex: 20, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 26, background: 'rgba(7,9,12,0.55)', backdropFilter: 'blur(4px)', WebkitBackdropFilter: 'blur(4px)', animation: 'cstFadeIn .18s ease' }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: '100%', maxWidth: 320, background: 'linear-gradient(180deg, #14171D, #0F1115)', border: `1px solid ${accent}44`,
        borderRadius: 16, padding: 18, boxShadow: '0 18px 50px -18px rgba(0,0,0,0.8)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
          <span style={{ fontFamily: _puF, fontWeight: 800, fontSize: 15, color: _puT }}>{info.title}</span>
          <button onClick={onClose} style={{ cursor: 'pointer', width: 28, height: 28, borderRadius: 8, background: _puG, border: `1px solid ${_puHR}`, color: _puH, fontSize: 13 }}>✕</button>
        </div>
        {info.value != null && <div style={{ fontFamily: _puF, fontWeight: 800, fontSize: 28, color: accent, letterSpacing: -0.5, marginBottom: 8 }}>{info.value}</div>}
        <p style={{ margin: 0, fontFamily: _puF, fontSize: 13, lineHeight: 1.5, color: 'rgba(236,237,241,0.86)' }}>{info.body}</p>
      </div>
    </div>);
}

// shared 99¢ report unlock: locked preview → slide-to-pay → unlocked sections + PDF download.
// props: accent, tool, price, includes:[str], sections:[{title, items?, body?}], buildSpec:()=>spec, filename, resultHash
function ReportUnlock({ accent, tool, price = '99¢', includes = [], sections = [], buildSpec, filename = 'cs-tech-report', resultHash }) {
  // Unlimited subscribers get all reports free
  const unlimited = window.CST_STATS && window.CST_STATS.isSubscribed();
  const [paid, setPaid] = _puS2(unlimited);
  const [showSlider, setShowSlider] = _puS2(false);
  const [busy, setBusy] = _puS2('');     // '', 'working', 'done', 'error'

  // Sync if subscription status changes after mount
  _puE2(() => { if (unlimited && !paid) setPaid(true); }, [unlimited]);

  // Check if already purchased on mount (non-subscribers only)
  _puE2(() => {
    if (unlimited || !resultHash) return;
    (async () => {
      const access = await window.CST_AUTH.checkAccess(resultHash, tool);
      if (access && access.reportPurchased) setPaid(true);
    })();
  }, [resultHash, tool]);

  const handlePurchase = async () => {
    // Check if user is logged in
    const session = await window.CST_AUTH.getSession();
    if (!session) {
      // Trigger login — the app-level LoginSheet will show
      window.dispatchEvent(new CustomEvent('cst-require-auth', { detail: { intent: 'report' } }));
      return;
    }
    // Start Stripe Checkout
    const url = await window.CST_AUTH.startCheckout('report', tool, resultHash || '');
    if (url) {
      window.location.href = url;
    } else {
      // Fallback: demo mode (local unlock)
      setPaid(true);
      setShowSlider(false);
    }
  };

  const download = async () => {
    if (busy === 'working') return;
    setBusy('working');
    try {
      const spec = buildSpec ? buildSpec() : null;
      const res = spec && window.CST_REPORT ? await window.CST_REPORT.downloadReportPDF(spec, filename) : null;
      setBusy(res ? 'done' : 'error');
    } catch (e) { setBusy('error'); }
    setTimeout(() => setBusy(''), 2600);
  };
  if (!paid) {
    return (
      <div style={{ borderRadius: 14, border: `1px solid ${accent}44`, background: accent + '10', padding: 14 }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 4 }}>
          <span style={{ fontFamily: _puF, fontWeight: 700, fontSize: 13.5, color: _puT }}>Full report</span>
          <span style={{ fontFamily: _puF, fontWeight: 800, fontSize: 14, color: accent }}>{price}</span>
        </div>
        <div style={{ fontFamily: _puF, fontSize: 10, letterSpacing: 1, color: _puHD, marginBottom: 10 }}>A 3–5 page PDF with charts, to keep & share</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 5, marginBottom: 12 }}>
          {includes.slice(0, 4).map((r) => (
            <div key={r} style={{ display: 'flex', gap: 8, alignItems: 'flex-start' }}>
              <span style={{ color: accent, fontSize: 11, flexShrink: 0 }}>→</span>
              <span style={{ fontFamily: _puF, fontSize: 11.5, lineHeight: 1.4, color: _puH }}>{r}</span>
            </div>
          ))}
        </div>
        {showSlider
          ? <SlideToBuy accent={accent} label="Slide to unlock for" price={price} onConfirm={handlePurchase} />
          : <button onClick={() => setShowSlider(true)} style={{ width: '100%', cursor: 'pointer', border: 'none', borderRadius: 12, padding: 13, fontFamily: _puF, fontWeight: 800, fontSize: 14, color: _puI, background: accent, letterSpacing: 0.3 }}>Download full report · {price}</button>}
      </div>);
  }
  return (
    <div style={{ borderRadius: 14, border: `1px solid ${accent}55`, background: accent + '12', padding: 14, display: 'flex', flexDirection: 'column', gap: 12 }}>
      <div style={{ fontFamily: _puF, fontSize: 11, letterSpacing: 1.5, color: accent }}>✓ FULL REPORT UNLOCKED</div>
      {sections.map((s, si) => (
        <div key={si}>
          <div style={{ fontFamily: _puF, fontSize: 10.5, letterSpacing: 1, color: accent, marginBottom: 5 }}>{s.title.toUpperCase()}</div>
          {s.body
            ? <p style={{ margin: 0, fontFamily: _puF, fontSize: 12, lineHeight: 1.5, color: 'rgba(236,237,241,0.86)' }}>{s.body}</p>
            : <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                {(s.items || []).map((it, i) => (
                  <div key={i} style={{ display: 'flex', gap: 8, alignItems: 'flex-start' }}>
                    <span style={{ color: accent, fontSize: 11, flexShrink: 0 }}>{s.ordered ? (i + 1) + '.' : '→'}</span>
                    <span style={{ fontFamily: _puF, fontSize: 12, lineHeight: 1.45, color: 'rgba(236,237,241,0.86)' }}>{it}</span>
                  </div>
                ))}
              </div>}
        </div>
      ))}
      <button onClick={download} style={{ width: '100%', cursor: 'pointer', border: `1px solid ${accent}66`, borderRadius: 11, padding: 12, fontFamily: _puF, fontWeight: 700, fontSize: 12.5, color: busy === 'error' ? '#FF7E6E' : accent, background: accent + '14', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>
        {busy === 'working' ? <React.Fragment><TypingDots color={accent} /> Building your PDF…</React.Fragment>
          : busy === 'done' ? '✓ Downloaded — check your files'
          : busy === 'error' ? 'Couldn’t generate — tap to retry'
          : 'Download full report (PDF) ↓'}
      </button>
    </div>);
}

Object.assign(window, { SlideToBuy, FactorDetail, InfoCard, ReportUnlock });
