// share-card.jsx — Verse of the Week shareable image generator
// Renders a 1080×1920 image to canvas with the verse, motto, and church mark.

function generateVerseShareCard({ verse, ref, seasonName, palette = 'parchment' }) {
  return new Promise(async (resolve, reject) => {
    try {
      // Wait for the display fonts to load — without this, the canvas falls back
      // to a generic serif before Cormorant has finished fetching, producing a
      // visibly different layout than the rest of the site.
      if (document.fonts && document.fonts.ready) {
        try { await document.fonts.ready; } catch (e) { /* keep going */ }
      }

      const W = 1080, H = 1920;
      const canvas = document.createElement('canvas');
      canvas.width = W; canvas.height = H;
      const ctx = canvas.getContext('2d');

    // ── Palette ─────────────────────────────────────────
    const palettes = {
      parchment: { bg: '#efe9dd', ink: '#1a1714', ink2: '#3a2c22', gold: '#b8893d', accent: '#7a2e2e', muted: 'rgba(26,23,20,0.5)' },
      candlelight: { bg: '#1a1410', ink: '#f0e2c4', ink2: '#d4c098', gold: '#daa24e', accent: '#c4623a', muted: 'rgba(240,226,196,0.5)' },
      sepia: { bg: '#e8d8b8', ink: '#2a1f15', ink2: '#4a3525', gold: '#9a6e30', accent: '#7a3525', muted: 'rgba(42,31,21,0.5)' },
    };
    const p = palettes[palette] || palettes.parchment;

    // ── Background fill ────────────────────────────────
    ctx.fillStyle = p.bg;
    ctx.fillRect(0, 0, W, H);

    // Soft warmth gradient
    const warm = ctx.createRadialGradient(W * 0.5, H * 0.3, 200, W * 0.5, H * 0.5, W);
    warm.addColorStop(0, p.gold + '22');
    warm.addColorStop(1, p.bg + '00');
    ctx.fillStyle = warm;
    ctx.fillRect(0, 0, W, H);

    // Paper grain
    const grainImg = ctx.getImageData(0, 0, W, H);
    const gd = grainImg.data;
    for (let i = 0; i < gd.length; i += 4) {
      const noise = (Math.random() - 0.5) * 18;
      gd[i]     = Math.max(0, Math.min(255, gd[i]     + noise));
      gd[i + 1] = Math.max(0, Math.min(255, gd[i + 1] + noise));
      gd[i + 2] = Math.max(0, Math.min(255, gd[i + 2] + noise));
    }
    ctx.putImageData(grainImg, 0, 0);

    // ── Inner border frame ─────────────────────────────
    const M = 70;
    ctx.strokeStyle = p.gold;
    ctx.lineWidth = 2;
    ctx.strokeRect(M, M, W - 2 * M, H - 2 * M);
    ctx.lineWidth = 1;
    ctx.globalAlpha = 0.5;
    ctx.strokeRect(M + 12, M + 12, W - 2 * M - 24, H - 2 * M - 24);
    ctx.globalAlpha = 1;

    // ── Corner ornaments ───────────────────────────────
    function corner(x, y, sx, sy) {
      ctx.save();
      ctx.translate(x, y); ctx.scale(sx, sy);
      ctx.strokeStyle = p.gold; ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(0, 50); ctx.quadraticCurveTo(0, 0, 50, 0);
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(0, 0, 5, 0, Math.PI * 2);
      ctx.fillStyle = p.gold; ctx.fill();
      ctx.restore();
    }
    corner(M + 12, M + 12, 1, 1);
    corner(W - M - 12, M + 12, -1, 1);
    corner(M + 12, H - M - 12, 1, -1);
    corner(W - M - 12, H - M - 12, -1, -1);

    // ── Top: Gothic arch with Celtic cross ──────────────
    const cx = W / 2;
    drawGothicArchSeal(ctx, cx, 290, 170, p);

    // ── Season tag ─────────────────────────────────────
    ctx.fillStyle = p.accent;
    ctx.font = '500 24px "JetBrains Mono", monospace';
    ctx.textAlign = 'center';
    drawTrackedText(ctx, (seasonName || 'Verse of the Week').toUpperCase(), cx, 470, 6);

    // ── Decorative rule with dot ───────────────────────
    ctx.strokeStyle = p.gold;
    ctx.lineWidth = 1;
    ctx.beginPath(); ctx.moveTo(cx - 200, 510); ctx.lineTo(cx - 30, 510); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(cx + 30, 510); ctx.lineTo(cx + 200, 510); ctx.stroke();
    ctx.fillStyle = p.gold;
    ctx.beginPath(); ctx.arc(cx, 510, 4, 0, Math.PI * 2); ctx.fill();

    // ── The verse — italic display serif, hand-set ─────
    ctx.fillStyle = p.ink;
    ctx.textAlign = 'center';
    // Drop-cap-style first letter via larger first character
    const verseLines = wrapText(ctx, verse, W - 280, '500 italic 56px "Cormorant Garamond", "EB Garamond", serif', 78);

    // Big quotation marks
    ctx.fillStyle = p.gold;
    ctx.globalAlpha = 0.35;
    ctx.font = '500 italic 240px "Cormorant Garamond", serif';
    ctx.fillText('“', cx - 380, 720);
    ctx.fillText('”', cx + 380, 720 + verseLines.length * 78 + 80);
    ctx.globalAlpha = 1;

    // Now the verse lines themselves
    ctx.fillStyle = p.ink;
    ctx.font = '500 italic 56px "Cormorant Garamond", "EB Garamond", serif';
    let yLine = 660;
    verseLines.forEach((line, i) => {
      ctx.fillText(line, cx, yLine);
      yLine += 78;
    });

    // Reference
    ctx.fillStyle = p.ink2;
    ctx.font = '500 32px "JetBrains Mono", monospace';
    drawTrackedText(ctx, '— ' + (ref || '').toUpperCase(), cx, yLine + 50, 4);

    // ── Bottom block: motto + church name ──────────────
    const baseY = H - M - 200;

    // Decorative trefoil divider
    ctx.fillStyle = p.gold;
    ctx.strokeStyle = p.gold; ctx.lineWidth = 1.5;
    drawTrefoil(ctx, cx, baseY - 30, 16);

    // Motto
    ctx.fillStyle = p.gold;
    ctx.font = '500 22px "JetBrains Mono", monospace';
    drawTrackedText(ctx, 'ANCIENT FAITH    ·    OPEN DOORS    ·    ABUNDANT LIFE', cx, baseY + 40, 4);

    // Church name
    ctx.fillStyle = p.ink;
    ctx.font = '500 italic 44px "Cormorant Garamond", serif';
    ctx.fillText('Monticello United Methodist', cx, baseY + 110);

    // Address
    ctx.fillStyle = p.ink2;
    ctx.font = '400 22px "Newsreader", serif';
    ctx.fillText('Monticello, Mississippi   ·   monticelloumc.church', cx, baseY + 150);

      // Output — toBlob is the modern API; if it returns null (some browsers
      // do this when the canvas is too large or memory-pressed) fall back to
      // a data URL so the user always sees something instead of an endless
      // spinner.
      canvas.toBlob((blob) => {
        if (blob) {
          resolve(blob);
          return;
        }
        try {
          const dataURL = canvas.toDataURL('image/png');
          // Convert data URL to a Blob so the modal's URL.createObjectURL works.
          const parts = dataURL.split(',');
          const byteString = atob(parts[1]);
          const u8 = new Uint8Array(byteString.length);
          for (let i = 0; i < byteString.length; i++) u8[i] = byteString.charCodeAt(i);
          resolve(new Blob([u8], { type: 'image/png' }));
        } catch (err) {
          reject(err);
        }
      }, 'image/png');
    } catch (err) {
      reject(err);
    }
  });
}

function wrapText(ctx, text, maxW, font, lh) {
  ctx.font = font;
  const words = text.split(/\s+/);
  const lines = [];
  let line = '';
  words.forEach(w => {
    const test = line ? line + ' ' + w : w;
    if (ctx.measureText(test).width > maxW && line) {
      lines.push(line);
      line = w;
    } else {
      line = test;
    }
  });
  if (line) lines.push(line);
  return lines;
}

function drawTrackedText(ctx, text, x, y, tracking) {
  // Approximate letter-spacing by drawing each char individually
  const total = [...text].map(ch => ctx.measureText(ch).width + tracking).reduce((a, b) => a + b, 0) - tracking;
  let cx = x - total / 2;
  for (const ch of text) {
    const w = ctx.measureText(ch).width;
    ctx.textAlign = 'left';
    ctx.fillText(ch, cx, y);
    cx += w + tracking;
  }
  ctx.textAlign = 'center';
}

// Gothic pointed arch with a Celtic cross inside, halo, and a single base
// rule — matches the line-art used at the top of the Manuscript hero.
// Coords are normalised to a 56×72 box (the same viewBox the SVG uses) and
// scaled to whatever final size is requested.
function drawGothicArchSeal(ctx, cx, cy, size, p) {
  const VW = 56, VH = 72;
  const scale = size / VW;
  const finalH = VH * scale;
  ctx.save();
  ctx.translate(cx - size / 2, cy - finalH / 2);
  ctx.scale(scale, scale);
  ctx.strokeStyle = p.gold;
  ctx.lineCap = 'round';
  ctx.lineJoin = 'round';

  // Gothic pointed arch
  ctx.lineWidth = 1.2 / scale * scale; // ≈ 1.2 in source units
  ctx.lineWidth = 1.2;
  ctx.beginPath();
  ctx.moveTo(6, 70);
  ctx.lineTo(6, 28);
  ctx.quadraticCurveTo(6, 6, 28, 4);
  ctx.quadraticCurveTo(50, 6, 50, 28);
  ctx.lineTo(50, 70);
  ctx.stroke();

  // Base
  ctx.beginPath();
  ctx.moveTo(4, 70);
  ctx.lineTo(52, 70);
  ctx.stroke();

  // Celtic cross — vertical bar
  ctx.lineWidth = 1.4;
  ctx.beginPath();
  ctx.moveTo(28, 18);
  ctx.lineTo(28, 64);
  ctx.stroke();

  // Celtic cross — horizontal crossbar
  ctx.beginPath();
  ctx.moveTo(14, 38);
  ctx.lineTo(42, 38);
  ctx.stroke();

  // Nimbus halo at intersection
  ctx.lineWidth = 1.2;
  ctx.beginPath();
  ctx.arc(28, 38, 9, 0, Math.PI * 2);
  ctx.stroke();

  // Tiny center dot
  ctx.fillStyle = p.gold;
  ctx.beginPath();
  ctx.arc(28, 38, 1.4, 0, Math.PI * 2);
  ctx.fill();

  ctx.restore();
}

function drawTrefoil(ctx, x, y, r) {
  ctx.save();
  ctx.translate(x, y);
  ctx.beginPath();
  ctx.arc(0, -r * 0.6, r * 0.5, 0, Math.PI * 2);
  ctx.arc(-r * 0.55, r * 0.3, r * 0.5, 0, Math.PI * 2);
  ctx.arc(r * 0.55, r * 0.3, r * 0.5, 0, Math.PI * 2);
  ctx.fill();
  ctx.restore();
}

// Mini monogram drawing on canvas (matches the SVG ChurchMark)
function drawMonogramSeal(ctx, cx, cy, size, p) {
  const s = size / 100; // viewBox is 100x100
  ctx.save();
  ctx.translate(cx - size / 2, cy - size / 2);
  ctx.scale(s, s);

  // Outer rings
  ctx.strokeStyle = p.gold;
  ctx.globalAlpha = 0.7;
  ctx.lineWidth = 1.5 / s;
  ctx.beginPath(); ctx.arc(50, 50, 46, 0, Math.PI * 2); ctx.stroke();
  ctx.globalAlpha = 0.4;
  ctx.lineWidth = 1 / s;
  ctx.beginPath(); ctx.arc(50, 50, 42, 0, Math.PI * 2); ctx.stroke();
  ctx.globalAlpha = 1;

  // M
  ctx.strokeStyle = p.ink;
  ctx.lineWidth = 4 / s;
  ctx.lineCap = 'round'; ctx.lineJoin = 'round';
  ctx.beginPath();
  ctx.moveTo(22, 78); ctx.lineTo(22, 26); ctx.lineTo(26, 22); ctx.lineTo(30, 22); ctx.lineTo(30, 76);
  ctx.moveTo(30, 22); ctx.lineTo(48, 56);
  ctx.moveTo(52, 56); ctx.lineTo(70, 22);
  ctx.moveTo(70, 22); ctx.lineTo(74, 22); ctx.lineTo(78, 26); ctx.lineTo(78, 78);
  ctx.moveTo(16, 78); ctx.lineTo(34, 78);
  ctx.moveTo(62, 78); ctx.lineTo(84, 78);
  ctx.stroke();

  // Cross
  ctx.strokeStyle = p.gold;
  ctx.lineWidth = 5 / s;
  ctx.beginPath();
  ctx.moveTo(50, 14); ctx.lineTo(50, 70);
  ctx.moveTo(40, 30); ctx.lineTo(60, 30);
  ctx.stroke();

  // Top finial
  ctx.fillStyle = p.gold;
  ctx.beginPath(); ctx.arc(50, 14, 2.5, 0, Math.PI * 2); ctx.fill();

  ctx.restore();
}

// ─────────────────────────────────────────────────────────────
// React modal — preview the card and download / share it
// ─────────────────────────────────────────────────────────────
function VerseShareModal({ open, onClose, theme, verse, cite }) {
  const [previewUrl, setPreviewUrl] = React.useState(null);
  const [generating, setGenerating] = React.useState(false);
  const [errorMsg, setErrorMsg] = React.useState('');
  const palette = theme.paletteName === 'Candlelight' ? 'candlelight'
                : theme.paletteName === 'Sepia' ? 'sepia' : 'parchment';

  React.useEffect(() => {
    if (!open) return;
    setGenerating(true);
    setErrorMsg('');
    setPreviewUrl(null);
    let cancelled = false;
    generateVerseShareCard({ verse, ref: cite, seasonName: theme.season.name, palette })
      .then(blob => {
        if (cancelled) return;
        if (!blob) { setErrorMsg("The card couldn't be generated. Try Save image, or screenshot the verse instead."); setGenerating(false); return; }
        const url = URL.createObjectURL(blob);
        setPreviewUrl(url);
        setGenerating(false);
      })
      .catch(err => {
        if (cancelled) return;
        console.error('share card generation failed:', err);
        setErrorMsg("The card couldn't be generated on this device. The verse text is still on the page; you can copy it instead.");
        setGenerating(false);
      });
    return () => {
      cancelled = true;
      if (previewUrl) URL.revokeObjectURL(previewUrl);
    };
    // eslint-disable-next-line
  }, [open, palette, verse, cite]);

  if (!open) return null;
  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, zIndex: 200,
      background: 'rgba(20,16,10,0.78)', backdropFilter: 'blur(6px)',
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      padding: 22, cursor: 'pointer',
      overflowY: 'auto',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        background: theme.paper, padding: 18, maxWidth: '88%',
        cursor: 'default', display: 'flex', flexDirection: 'column', gap: 14,
      }}>
        <div style={{ ...smallCaps(theme, 9), color: theme.accent, textAlign: 'center', marginBottom: 2 }}>
          † &nbsp; A share card for {theme.season.name} &nbsp; †
        </div>
        <div style={{ position: 'relative', width: 280, aspectRatio: '1080 / 1920', background: theme.bgAlt, alignSelf: 'center' }}>
          {generating && (
            <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: theme.fonts.display, fontStyle: 'italic', color: theme.inkMute }}>
              Pressing the page…
            </div>
          )}
          {!generating && errorMsg && (
            <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center', padding: 16, fontFamily: theme.fonts.body, fontSize: 13, color: theme.inkSoft, fontStyle: 'italic' }}>
              {errorMsg}
            </div>
          )}
          {previewUrl && (
            <img src={previewUrl} style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }}/>
          )}
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button onClick={onClose} style={{
            flex: 1, padding: '12px 14px', background: 'transparent', color: theme.ink,
            border: `1px solid ${theme.rule}`, fontFamily: theme.fonts.mono, fontSize: 10,
            letterSpacing: '0.18em', textTransform: 'uppercase', cursor: 'pointer',
          }}>Close</button>
          <button
            disabled={!previewUrl}
            onClick={async () => {
              if (!previewUrl) return;
              const filename = `MUMC-verse-${(theme.season.name || 'card').replace(/\s+/g, '-')}.png`;
              try {
                const blob = await fetch(previewUrl).then(r => r.blob());
                if (navigator.canShare && navigator.canShare({ files: [new File([blob], filename, { type: 'image/png' })] })) {
                  await navigator.share({
                    files: [new File([blob], filename, { type: 'image/png' })],
                    title: 'A verse from Monticello UMC',
                  });
                  return;
                }
              } catch (e) { /* fall back to download */ }
              const a = document.createElement('a');
              a.href = previewUrl;
              a.download = filename;
              document.body.appendChild(a);
              a.click();
              a.remove();
            }}
            style={{
              flex: 1.6, padding: '12px 14px',
              background: previewUrl ? theme.ink : theme.inkMute,
              color: theme.paper,
              border: 'none', cursor: previewUrl ? 'pointer' : 'not-allowed',
              fontFamily: theme.fonts.mono, fontSize: 10,
              letterSpacing: '0.18em', textTransform: 'uppercase', textAlign: 'center',
            }}>↗ &nbsp; Share or save</button>
        </div>
        <div style={{ fontFamily: theme.fonts.display, fontStyle: 'italic', fontSize: 13, color: theme.inkMute, textAlign: 'center', lineHeight: 1.4 }}>
          A printed verse, hand-set on parchment.<br/>Share to Instagram, text it to a friend, frame it.
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { generateVerseShareCard, VerseShareModal });
