// cro.jsx — conversion-rate-optimization modules:
//   - Discount state (sessionStorage + event bus)
//   - Exit-intent modal (mouseleave-top, $25 off)
//   - Sticky mobile CTA bar
//   - Save-quiz-progress dialog
//   - Session POST to Cloudflare Worker (saveQuizSession)

const { useState: _u, useEffect: _e, useRef: _r } = React;

// ════════════════════════════════════════════════════════════════════════════
//  Session storage — POSTs quiz answers + recommendation to the Worker,
//  returns a session ID that gets appended to the sticky.io checkout URL.
// ════════════════════════════════════════════════════════════════════════════
const SESSION_KEY = 'hrx_session_id';

function getApiBase() {
  // Allow override via <script>window.HRX_API_BASE = '...'</script>
  if (typeof window !== 'undefined' && window.HRX_API_BASE) return window.HRX_API_BASE;
  // Default: same origin (Worker mounted at /api/* on the same domain)
  return '';
}

function getStoredSessionId() {
  try { return sessionStorage.getItem(SESSION_KEY); } catch { return null; }
}
function setStoredSessionId(id) {
  try { sessionStorage.setItem(SESSION_KEY, id); } catch {}
}
function clearStoredSessionId() {
  try { sessionStorage.removeItem(SESSION_KEY); } catch {}
}

// Capture utm_* and gclid/fbclid from the URL so we can persist them.
function readMarketingParams() {
  try {
    const sp = new URLSearchParams(location.search);
    const m = {};
    for (const [k, v] of sp.entries()) {
      if (/^(utm_|gclid|fbclid|ttclid|msclkid)/i.test(k)) m[k] = v;
    }
    return m;
  } catch { return {}; }
}

async function saveQuizSession({ answers, recommendation, discount }) {
  const base = getApiBase();
  // Already saved? Re-use the cached ID so we don't double-write.
  const existing = getStoredSessionId();
  if (existing) return existing;

  const payload = {
    answers,
    recommendation,
    discount,
    metadata: {
      ...readMarketingParams(),
      landingUrl: location.href,
      timestamp: Date.now(),
    },
  };

  try {
    const res = await fetch(`${base}/api/sessions`, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(payload),
      keepalive: true,
    });
    if (!res.ok) throw new Error(`status ${res.status}`);
    const data = await res.json();
    if (data.sessionId) {
      setStoredSessionId(data.sessionId);
      return data.sessionId;
    }
  } catch (err) {
    // Graceful degradation: if Worker is unreachable, checkout still proceeds
    // (just without the session ID). We log to console for visibility.
    console.warn('[hrx] saveQuizSession failed:', err);
  }
  return null;
}

function useStoredSessionId() {
  const [id, setId] = _u(getStoredSessionId);
  _e(() => {
    const h = () => setId(getStoredSessionId());
    window.addEventListener('storage', h);
    return () => window.removeEventListener('storage', h);
  }, []);
  return id;
}

// ════════════════════════════════════════════════════════════════════════════
//  Discount state — single source of truth, available everywhere
// ════════════════════════════════════════════════════════════════════════════
const DISCOUNT_KEY = 'hrx_discount';
const DISCOUNT_EVT = 'hrx-discount-change';

const DISCOUNTS = {
  FIRST25:    { code: 'FIRST25',    amount: 25, label: '$25 off your first month', source: 'exit-intent' },
};

function getDiscount() {
  try {
    const raw = sessionStorage.getItem(DISCOUNT_KEY);
    if (!raw) return null;
    const obj = JSON.parse(raw);
    return DISCOUNTS[obj.code] || obj;
  } catch { return null; }
}
function applyDiscount(code) {
  const d = DISCOUNTS[code];
  if (!d) return;
  sessionStorage.setItem(DISCOUNT_KEY, JSON.stringify(d));
  window.dispatchEvent(new CustomEvent(DISCOUNT_EVT));
}
function clearDiscount() {
  sessionStorage.removeItem(DISCOUNT_KEY);
  window.dispatchEvent(new CustomEvent(DISCOUNT_EVT));
}

function useDiscount() {
  const [d, setD] = _u(getDiscount);
  _e(() => {
    const h = () => setD(getDiscount());
    window.addEventListener(DISCOUNT_EVT, h);
    return () => window.removeEventListener(DISCOUNT_EVT, h);
  }, []);
  return d;
}

// ════════════════════════════════════════════════════════════════════════════
//  ExitIntentModal — fires on mouseleave at top of viewport (desktop) or
//  after 30s of inactivity / 50% scroll without action (mobile).
//  Shows once per session.
// ════════════════════════════════════════════════════════════════════════════
const EXIT_SHOWN_KEY = 'hrx_exit_shown';

function ExitIntentModal({ onAccept }) {
  const [open, setOpen] = _u(false);
  const [accepted, setAccepted] = _u(false);
  const armedRef = _r(true);

  _e(() => {
    if (sessionStorage.getItem(EXIT_SHOWN_KEY)) return;

    // Desktop: mouseleave top
    const onMouseLeave = (e) => {
      if (!armedRef.current) return;
      if (e.clientY <= 0) { fire(); }
    };
    // Mobile fallback: timer + scroll heuristic
    const t = setTimeout(() => { if (armedRef.current && window.innerWidth < 720) fire(); }, 45_000);

    function fire() {
      armedRef.current = false;
      sessionStorage.setItem(EXIT_SHOWN_KEY, '1');
      setOpen(true);
    }

    document.addEventListener('mouseleave', onMouseLeave);
    return () => {
      document.removeEventListener('mouseleave', onMouseLeave);
      clearTimeout(t);
    };
  }, []);

  const close = () => setOpen(false);
  const accept = () => {
    applyDiscount('FIRST25');
    setAccepted(true);
    setTimeout(() => { setOpen(false); onAccept?.(); }, 1200);
  };

  if (!open) return null;
  return (
    <div role="dialog" aria-modal="true"
         style={{
           position: 'fixed', inset: 0, zIndex: 200,
           background: 'rgba(12,33,36,.55)',
           backdropFilter: 'blur(6px)',
           display: 'grid', placeItems: 'center',
           padding: 20,
           animation: 'fadeIn .2s ease',
         }}
         onClick={(e) => { if (e.target === e.currentTarget) close(); }}>
      <div style={{
        position: 'relative',
        background: 'var(--bg)',
        border: '1px solid var(--line)',
        borderRadius: 'var(--r-xl)',
        maxWidth: 520, width: '100%',
        padding: '36px 36px 32px',
        boxShadow: '0 40px 80px -20px rgba(0,0,0,.5)',
        animation: 'modalIn .3s cubic-bezier(.2,.7,.2,1)',
      }}>
        <button onClick={close} aria-label="Close"
                style={{
                  position: 'absolute', top: 14, right: 14,
                  width: 32, height: 32, borderRadius: 32,
                  background: 'transparent', border: 0, color: 'var(--ink-dim)',
                  fontSize: 18, lineHeight: 1, cursor: 'pointer',
                }}>×</button>

        {!accepted ? (
          <>
            <div style={{
              display: 'inline-flex', alignItems: 'center', gap: 8,
              padding: '4px 12px', borderRadius: 999,
              background: 'color-mix(in oklab, var(--brand-yellow) 38%, transparent)',
              color: 'var(--ink)',
              border: '1px solid color-mix(in oklab, var(--brand-yellow) 65%, transparent)',
              fontSize: 10.5, letterSpacing: '.14em', textTransform: 'uppercase',
              whiteSpace: 'nowrap',
            }}>● Wait — one thing</div>

            <h2 style={{
              marginTop: 18,
              fontFamily: 'var(--serif)', fontSize: 'clamp(34px, 4.4vw, 44px)',
              lineHeight: 1.1, letterSpacing: '-.012em',
            }}>
              Take <em style={{ fontStyle: 'italic', color: 'var(--accent)' }}>$25 off</em>
              <br/>your first month.
            </h2>
            <p style={{
              marginTop: 14, fontSize: 15, lineHeight: 1.55, color: 'var(--ink-dim)',
              maxWidth: 420,
            }}>
              Complete your free assessment in the next 24 hours and we'll knock
              <strong style={{ color: 'var(--ink)' }}> $25 off</strong> your first month's prescription.
              No code to remember — it'll apply automatically at checkout.
            </p>

            <div style={{
              marginTop: 22, padding: '14px 18px',
              background: 'var(--surface)',
              border: '1px dashed var(--line-strong)',
              borderRadius: 'var(--r-md)',
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              gap: 12,
            }}>
              <div>
                <div style={{ fontSize: 10.5, letterSpacing: '.18em', textTransform: 'uppercase', color: 'var(--ink-mute)' }}>
                  Your code
                </div>
                <div style={{
                  fontFamily: 'var(--mono)', fontSize: 22, fontWeight: 500,
                  letterSpacing: '.08em', marginTop: 2,
                }}>FIRST25</div>
              </div>
              <div style={{
                fontFamily: 'var(--serif)', fontSize: 28, color: 'var(--accent)',
              }}>−$25</div>
            </div>

            <div style={{ marginTop: 22, display: 'flex', gap: 10, flexWrap: 'wrap' }}>
              <button onClick={accept} style={{ ...btn.big, padding: '14px 22px', fontSize: 15 }}>
                Apply $25 off & continue
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14"/><path d="M13 5l7 7-7 7"/></svg>
              </button>
              <button onClick={close} style={btn.ghost}>No thanks</button>
            </div>
          </>
        ) : (
          <div style={{ textAlign: 'center', padding: '20px 0 6px' }}>
            <div style={{
              width: 58, height: 58, borderRadius: 58, margin: '0 auto',
              background: 'color-mix(in oklab, var(--brand-yellow) 38%, transparent)',
              border: '1px solid color-mix(in oklab, var(--brand-yellow) 65%, transparent)',
              display: 'grid', placeItems: 'center',
            }}>
              <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="var(--ink)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M4 12l5 5L20 6"/>
              </svg>
            </div>
            <h3 style={{ marginTop: 16, fontFamily: 'var(--serif)', fontSize: 28 }}>
              Discount locked in.
            </h3>
            <p style={{ marginTop: 8, fontSize: 14, color: 'var(--ink-dim)' }}>
              Taking you to your assessment…
            </p>
          </div>
        )}
      </div>
      <style>{`
        @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
        @keyframes modalIn {
          from { opacity: 0; transform: translateY(20px) scale(.96); }
          to   { opacity: 1; transform: none; }
        }
      `}</style>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════════
//  ActiveDiscountBanner — slim bar that shows when a discount is active
// ════════════════════════════════════════════════════════════════════════════
function ActiveDiscountBanner() {
  const d = useDiscount();
  if (!d) return null;
  return (
    <div style={{
      position: 'fixed', left: 16, bottom: 16, zIndex: 80,
      background: 'var(--ink)', color: 'var(--bg)',
      borderRadius: 999,
      padding: '8px 14px 8px 8px',
      display: 'flex', alignItems: 'center', gap: 10,
      boxShadow: '0 10px 30px -10px rgba(0,0,0,.4)',
      fontSize: 12.5, animation: 'slideUp .35s cubic-bezier(.2,.7,.2,1)',
      maxWidth: 'calc(100vw - 32px)',
    }}>
      <span style={{
        width: 26, height: 26, borderRadius: 26,
        background: 'var(--brand-yellow)',
        color: 'var(--ink)', display: 'grid', placeItems: 'center',
        fontFamily: 'var(--serif)', fontSize: 14, fontStyle: 'italic',
      }}>$</span>
      <span style={{ whiteSpace: 'nowrap' }}>
        <strong>{d.code}</strong> · ${d.amount} off applied at checkout
      </span>
      <button onClick={clearDiscount}
              aria-label="Remove discount"
              style={{
                background: 'transparent', border: 0, color: 'rgba(255,255,255,.6)',
                cursor: 'pointer', padding: '0 4px', fontSize: 15,
              }}>×</button>
      <style>{`@keyframes slideUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }`}</style>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════════
//  Sticky mobile CTA bar — fixed bottom on small screens
// ════════════════════════════════════════════════════════════════════════════
function StickyMobileCTA({ go, hide }) {
  const [visible, setVisible] = _u(false);
  _e(() => {
    const update = () => {
      const isMobile = window.innerWidth < 720;
      const scrolled = window.scrollY > 400;
      setVisible(isMobile && scrolled && !hide);
    };
    update();
    window.addEventListener('scroll', update, { passive: true });
    window.addEventListener('resize', update);
    return () => { window.removeEventListener('scroll', update); window.removeEventListener('resize', update); };
  }, [hide]);

  if (!visible) return null;
  const fromPrice = (typeof fromPricePerMonth === 'function')
    ? Math.round(fromPricePerMonth('sildenafil') || 36)
    : 36;
  return (
    <div style={{
      position: 'fixed', left: 0, right: 0, bottom: 0, zIndex: 70,
      background: 'color-mix(in oklab, var(--bg) 95%, transparent)',
      backdropFilter: 'blur(14px)',
      WebkitBackdropFilter: 'blur(14px)',
      borderTop: '1px solid var(--line-strong)',
      padding: '12px 16px calc(12px + env(safe-area-inset-bottom))',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      gap: 12,
      animation: 'slideUpMobile .3s cubic-bezier(.2,.7,.2,1)',
    }}>
      <div style={{ minWidth: 0 }}>
        <div style={{
          fontSize: 11, letterSpacing: '.12em', textTransform: 'uppercase',
          color: 'var(--ink-mute)', marginBottom: 2,
        }}>From ${fromPrice}/mo</div>
        <div style={{
          fontFamily: 'var(--serif)', fontSize: 18, lineHeight: 1,
        }}>3-minute assessment</div>
      </div>
      <button onClick={() => go('quiz')} style={{ ...btn.solid, padding: '13px 18px', fontSize: 14 }}>
        See if you qualify →
      </button>
      <style>{`@keyframes slideUpMobile { from { transform: translateY(100%); } to { transform: none; } }`}</style>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════════
//  Save quiz progress dialog
// ════════════════════════════════════════════════════════════════════════════
function SaveProgressBanner({ onSave }) {
  const [saved, setSaved] = _u(() => !!localStorage.getItem('hrx_quiz_email'));
  const [email, setEmail] = _u('');
  const [open, setOpen] = _u(false);

  if (saved) return null;

  if (!open) {
    return (
      <div style={{
        marginTop: 32, padding: '14px 18px',
        background: 'var(--surface-2)',
        border: '1px dashed var(--line-strong)',
        borderRadius: 'var(--r-md)',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        gap: 14, flexWrap: 'wrap',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 13, color: 'var(--ink-dim)' }}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
            <path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
          </svg>
          Save your progress — we'll text or email you a link to pick up where you left off.
        </div>
        <button onClick={() => setOpen(true)} style={{ ...btn.outline, padding: '8px 14px', fontSize: 13 }}>
          Save progress
        </button>
      </div>
    );
  }

  const ok = email && /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email);
  return (
    <div style={{
      marginTop: 32, padding: '16px 18px',
      background: 'var(--surface)',
      border: '1px solid var(--accent)',
      borderRadius: 'var(--r-md)',
    }}>
      <div style={{ fontSize: 13.5, fontWeight: 500, marginBottom: 10 }}>
        Where should we send your link?
      </div>
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
        <input type="email" autoFocus value={email} placeholder="you@example.com"
               onChange={(e) => setEmail(e.target.value)}
               style={{
                 all: 'unset', flex: 1, minWidth: 200,
                 padding: '11px 14px',
                 background: 'var(--bg)',
                 border: '1px solid var(--line-strong)',
                 borderRadius: 'var(--r-md)',
                 fontSize: 14, color: 'var(--ink)',
               }} />
        <button disabled={!ok}
                onClick={() => {
                  localStorage.setItem('hrx_quiz_email', email);
                  onSave?.(email);
                  setSaved(true);
                }}
                style={{
                  ...btn.solid, padding: '11px 18px', fontSize: 13.5,
                  opacity: ok ? 1 : 0.4,
                  cursor: ok ? 'pointer' : 'not-allowed',
                }}>
          Send me the link
        </button>
      </div>
      <div style={{ marginTop: 8, fontSize: 11, color: 'var(--ink-mute)' }}>
        We'll only use this to send your save link and your physician's response.
      </div>
    </div>
  );
}

Object.assign(window, {
  getDiscount, applyDiscount, clearDiscount, useDiscount,
  ExitIntentModal, ActiveDiscountBanner, StickyMobileCTA, SaveProgressBanner,
  DISCOUNTS,
  saveQuizSession, useStoredSessionId, getStoredSessionId, clearStoredSessionId,
});
