// ─────────────────────────────────────────────────────────────────────────────
// DOWNLOAD DELIVERY  —  the secure "get your file" block on the Thank-you page.
//
// Rendered by all four payment-breakpoint success screens. After a real
// payment it asks the Cloudflare Worker (see delivery-config.js + SETUP.md
// Part D) to verify the charge and mint a short-lived signed token, then shows
// a Download button pointing at  <worker>/download?token=…  — or a "Watch now"
// link for video products. With no Worker configured it runs in DEMO mode and
// shows a sample link so the design is previewable.
//
// States:  minting → ready → expired      (and an error fallback)
// ─────────────────────────────────────────────────────────────────────────────

// Per-breakpoint sizing. Keeps the block proportional to each success screen.
const DD_SIZES = {
  desktop: { card: 30, gap: 20, icon: 56, title: 21, sub: 15, ctaFs: 19, ctaPad: '20px 40px', meta: 15, radius: 22 },
  tablet: { card: 26, gap: 18, icon: 52, title: 19, sub: 14, ctaFs: 18, ctaPad: '18px 34px', meta: 14, radius: 20 },
  lmob: { card: 20, gap: 14, icon: 46, title: 17, sub: 13, ctaFs: 16, ctaPad: '16px 28px', meta: 13, radius: 18 },
  smob: { card: 18, gap: 12, icon: 42, title: 16, sub: 12.5, ctaFs: 15, ctaPad: '15px 24px', meta: 12.5, radius: 16 }
};

// Random hex token used only in demo mode (no Worker configured).
function ddDemoToken() {
  try {
    return [...crypto.getRandomValues(new Uint8Array(18))].
    map((b) => b.toString(16).padStart(2, '0')).join('');
  } catch (e) {
    return Math.random().toString(16).slice(2) + Math.random().toString(16).slice(2);
  }
}

// "23h 59m" / "8m" / "42s" — compact remaining-time label.
function ddRemaining(ms) {
  if (ms <= 0) return null;
  const s = Math.floor(ms / 1000);
  const h = Math.floor(s / 3600);
  const m = Math.floor(s % 3600 / 60);
  if (h >= 1) return `${h}h ${m}m`;
  if (m >= 1) return `${m}m`;
  return `${s % 60}s`;
}

// Glyphs ----------------------------------------------------------------------
const DDDownloadIcon = ({ size = 22, color = '#fff' }) =>
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
    <path d="M12 3v12m0 0l-4.5-4.5M12 15l4.5-4.5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    <path d="M4 17v2.5A1.5 1.5 0 0 0 5.5 21h13a1.5 1.5 0 0 0 1.5-1.5V17" stroke={color} strokeWidth="2" strokeLinecap="round" />
  </svg>;

const DDPlayIcon = ({ size = 22, color = '#fff' }) =>
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
    <path d="M8 5.5v13l11-6.5-11-6.5z" fill={color} stroke={color} strokeWidth="1.6" strokeLinejoin="round" />
  </svg>;

const DDFileGlyph = ({ size = 26, color = '#6f6259' }) =>
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" style={{ height: "25px", width: "25px" }}>
    <path d="M6 2.5h7l5 5V20a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 6 20V4A1.5 1.5 0 0 1 7.5 2.5z" stroke={color} strokeWidth="1.6" strokeLinejoin="round" />
    <path d="M13 2.5V7a1 1 0 0 0 1 1h4" stroke={color} strokeWidth="1.6" strokeLinejoin="round" />
  </svg>;

const DDClock = ({ size = 14, color = '#91837a' }) =>
<svg width={size} height={size} viewBox="0 0 16 16" fill="none" style={{ flexShrink: 0 }}>
    <circle cx="8" cy="8" r="6.2" stroke={color} strokeWidth="1.4" />
    <path d="M8 4.6V8l2.4 1.6" stroke={color} strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
  </svg>;

// Main component --------------------------------------------------------------
const DownloadDelivery = ({ product, email, paymentIntentId, variant = 'desktop' }) => {
  const S = DD_SIZES[variant] || DD_SIZES.desktop;
  const isVideo = (product && product.delivery) === 'watch';
  const assetLabel = product && product.assetLabel || (isVideo ? 'Video access' : 'Digital download');
  const ttlMin = window.DELIVERY_CONFIG && window.DELIVERY_CONFIG.linkTtlMinutes || 1440;

  const [phase, setPhase] = React.useState('minting'); // minting | ready | expired | error
  const [url, setUrl] = React.useState('');
  const [expiresAt, setExp] = React.useState(0);
  const [now, setNow] = React.useState(Date.now());
  const [resent, setResent] = React.useState(false);

  // Mint (or re-mint) a token. Real call when a Worker is configured; otherwise
  // a demo link so the Thank-you page is fully previewable with no backend.
  const issue = React.useCallback(async () => {
    setPhase('minting');
    setResent(false);
    const configured = typeof window.isDeliveryConfigured === 'function' && window.isDeliveryConfigured();
    if (!configured) {
      // ── DEMO MODE ──────────────────────────────────────────────────────
      await new Promise((r) => setTimeout(r, 650)); // let the "preparing…" state read
      const base = (window.DELIVERY_CONFIG && window.DELIVERY_CONFIG.workerBaseUrl || '').trim().replace(/\/$/, '');
      const path = isVideo ? '/watch' : '/download';
      setUrl(`${base || 'https://delivery.example.workers.dev'}${path}?token=${ddDemoToken()}`);
      setExp(Date.now() + ttlMin * 60000);
      setPhase('ready');
      return;
    }
    // ── LIVE MODE ────────────────────────────────────────────────────────
    try {
      const base = window.DELIVERY_CONFIG.workerBaseUrl.trim().replace(/\/$/, '');
      const r = await fetch(`${base}/issue`, {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({
          paymentIntentId: paymentIntentId || null,
          email: email || null,
          product: product && product.id || null
        })
      });
      const data = await r.json().catch(() => ({}));
      if (!r.ok || !data.url) throw new Error(data && data.error || 'issue failed');
      setUrl(data.url);
      setExp(data.expiresAt || Date.now() + ttlMin * 60000);
      setPhase('ready');
    } catch (e) {
      setPhase('error');
    }
  }, [isVideo, ttlMin, paymentIntentId, email, product]);

  React.useEffect(() => {issue();}, [issue]);

  // Tick once a minute so the "expires in …" label stays fresh and flips to
  // the expired state when the window closes.
  React.useEffect(() => {
    if (phase !== 'ready') return;
    const id = setInterval(() => setNow(Date.now()), 30000);
    return () => clearInterval(id);
  }, [phase]);

  React.useEffect(() => {
    if (phase === 'ready' && expiresAt && now >= expiresAt) setPhase('expired');
  }, [now, expiresAt, phase]);

  const remaining = ddRemaining(expiresAt - now);

  // Resend the link to the buyer's email (the Worker also emails it on the
  // webhook, so this is a manual "send it again"). Demo: just confirm.
  const resend = async () => {
    setResent(true);
    const configured = typeof window.isDeliveryConfigured === 'function' && window.isDeliveryConfigured();
    if (!configured) return;
    try {
      const base = window.DELIVERY_CONFIG.workerBaseUrl.trim().replace(/\/$/, '');
      await fetch(`${base}/resend`, {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ paymentIntentId: paymentIntentId || null, email: email || null, product: product && product.id || null })
      });
    } catch (e) {/* keep the optimistic "sent" — Worker also emails on webhook */}
  };

  const ctaLabel = isVideo ? 'Watch now' : 'Download now';
  const CtaIcon = isVideo ? DDPlayIcon : DDDownloadIcon;

  return (
    <div style={{
      width: '100%', maxWidth: variant === 'desktop' ? 560 : variant === 'tablet' ? 480 : '100%',
      background: '#fffbf9', border: '1px solid #f0e6dc', borderRadius: S.radius,
      padding: S.card, display: 'flex', flexDirection: 'column', gap: S.gap,
      boxShadow: '0 18px 50px -28px rgba(120,70,30,0.28)', textAlign: 'left',
      boxSizing: 'border-box'
    }}>
      {/* Asset row — what they're getting */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        <div style={{
          width: S.icon, height: S.icon, flexShrink: 0, borderRadius: 14,
          background: '#f4e8dd', display: 'grid', placeItems: 'center'
        }}>
          {isVideo ? <DDPlayIcon size={S.icon * 0.44} color="#6f6259" /> : <DDFileGlyph size={S.icon * 0.5} color="#6f6259" />}
        </div>
        <div style={{ minWidth: 0 }}>
          <div style={{
            fontFamily: 'Inter', fontWeight: 600, fontSize: S.title, color: '#101010',
            letterSpacing: '-0.02em', lineHeight: 1.2, overflow: 'hidden', textOverflow: 'ellipsis'
          }}>{product && product.title || 'Your purchase'}</div>
          <div style={{
            fontFamily: 'Inter', fontWeight: 500, fontSize: S.sub, color: '#91837a',
            letterSpacing: '0.02em', marginTop: 3
          }}>{product && product.subLabel || 'Template on Notion'}</div>
        </div>
      </div>

      {/* CTA + states */}
      {phase === 'minting' &&
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10, padding: '6px 0' }}>
          <span className="dd-spin" style={{
          width: 18, height: 18, borderRadius: '50%',
          border: '2.5px solid #e7d8ca', borderTopColor: '#101010', display: 'inline-block'
        }} />
          <span style={{ fontFamily: 'Inter', fontWeight: 500, fontSize: S.meta, color: '#6f6259', letterSpacing: '-0.01em' }}>
            Preparing your secure {isVideo ? 'access link' : 'download'}…
          </span>
        </div>
      }

      {phase === 'ready' &&
      <React.Fragment>
          <a href={url} target="_blank" rel="noopener" download={isVideo ? undefined : ''}
        style={{
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12,
          padding: S.ctaPad, borderRadius: 80, background: '#101010', color: '#fff',
          fontFamily: 'Inter', fontWeight: 600, fontSize: S.ctaFs, letterSpacing: '-0.01em',
          textDecoration: 'none', cursor: 'pointer', transition: 'transform 160ms ease, background 160ms ease'
        }}
        onMouseEnter={(e) => {e.currentTarget.style.background = '#262626';e.currentTarget.style.transform = 'translateY(-1px)';}}
        onMouseLeave={(e) => {e.currentTarget.style.background = '#101010';e.currentTarget.style.transform = 'none';}}>
            <CtaIcon size={S.ctaFs * 1.1} color="#fff" />
            {ctaLabel}
          </a>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7 }}>
            <DDClock size={S.meta} color="#91837a" />
            <span style={{ fontFamily: 'Inter', fontWeight: 500, fontSize: S.meta, color: '#91837a', letterSpacing: '-0.01em' }}>
              {remaining ? `Link active for ${remaining}` : 'Link active for a limited time'}
            </span>
          </div>
        </React.Fragment>
      }

      {phase === 'expired' &&
      <React.Fragment>
          <button onClick={issue} style={{
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10,
          padding: S.ctaPad, borderRadius: 80, background: 'transparent', color: '#101010',
          border: '1.5px solid #101010', fontFamily: 'Inter', fontWeight: 600, fontSize: S.ctaFs,
          letterSpacing: '-0.01em', cursor: 'pointer'
        }}>
            Get a fresh link
          </button>
          <div style={{ fontFamily: 'Inter', fontWeight: 500, fontSize: S.meta, color: '#91837a', textAlign: 'center', letterSpacing: '-0.01em' }}>
            That link expired to keep your purchase private. Generate a new one — it's yours.
          </div>
        </React.Fragment>
      }

      {phase === 'error' &&
      <div style={{ fontFamily: 'Inter', fontSize: S.meta, color: '#6f6259', lineHeight: 1.5, letterSpacing: '-0.01em' }}>
          We couldn't prepare your link just now. {email ? <React.Fragment>We've also emailed it to <strong style={{ color: '#101010' }}>{email}</strong>.</React.Fragment> : 'Please check the email used at checkout.'}{' '}
          <button onClick={issue} style={{ background: 'none', border: 'none', padding: 0, color: '#101010', fontWeight: 600, fontFamily: 'Inter', fontSize: S.meta, textDecoration: 'underline', cursor: 'pointer' }}>Try again</button>
        </div>
      }

      <style>{`@keyframes dd-spin { to { transform: rotate(360deg); } } .dd-spin { animation: dd-spin 700ms linear infinite; }`}</style>
    </div>);

};

Object.assign(window, { DownloadDelivery });