// Quote Card Generator — create beautiful shareable quote images on canvas.

(function () {

  const FONTS = [
    { label: 'Playfair Display', value: 'Playfair Display', gfont: 'Playfair+Display:wght@400;700' },
    { label: 'Lora',             value: 'Lora',             gfont: 'Lora:wght@400;700' },
    { label: 'Merriweather',     value: 'Merriweather',     gfont: 'Merriweather:wght@400;700' },
    { label: 'Georgia',          value: 'Georgia',          gfont: null },
    { label: 'Poppins',          value: 'Poppins',          gfont: 'Poppins:wght@400;600;700' },
  ];

  const BACKGROUNDS = [
    { label: 'Sunset',   grad: ['#f97316', '#ec4899'], text: '#fff' },
    { label: 'Ocean',    grad: ['#3b82f6', '#14b8a6'], text: '#fff' },
    { label: 'Night',    grad: ['#581c87', '#0a0a0a'], text: '#fff' },
    { label: 'Forest',   grad: ['#22c55e', '#14532d'], text: '#fff' },
    { label: 'Lavender', grad: ['#a855f7', '#ec4899'], text: '#fff' },
    { label: 'Minimal',  grad: ['#ffffff', '#ffffff'], text: '#111' },
    { label: 'Dark',     grad: ['#1f2937', '#111827'], text: '#f9fafb' },
    { label: 'Custom',   grad: null, text: '#fff' },
  ];

  const RATIOS = [
    { label: 'Square',    w: 1080, h: 1080 },
    { label: 'Story',     w: 1080, h: 1920 },
    { label: 'Landscape', w: 1200, h: 630 },
  ];

  const ALIGNS = ['left', 'center', 'right'];

  // Ensure Google Font CSS is loaded once per font family.
  const _loadedFonts = {};
  function ensureFont(font) {
    if (!font.gfont || _loadedFonts[font.value]) return;
    _loadedFonts[font.value] = true;
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = 'https://fonts.googleapis.com/css2?family=' + font.gfont + '&display=swap';
    document.head.appendChild(link);
  }

  // Word-wrap a string to fit within maxWidth on a 2d context.
  function wrapText(ctx, text, maxWidth) {
    const words = text.split(/\s+/);
    const lines = [];
    let line = '';
    for (let i = 0; i < words.length; i++) {
      const test = line ? line + ' ' + words[i] : words[i];
      if (ctx.measureText(test).width > maxWidth && line) {
        lines.push(line);
        line = words[i];
      } else {
        line = test;
      }
    }
    if (line) lines.push(line);
    return lines;
  }

  window.TOOL_HANDLERS['quote-card'] = function QuoteCardTool() {
    const [quote, setQuote]       = React.useState('The only way to do great work is to love what you do.');
    const [author, setAuthor]     = React.useState('Steve Jobs');
    const [bgIdx, setBgIdx]       = React.useState(0);
    const [fontIdx, setFontIdx]   = React.useState(0);
    const [fontSize, setFontSize] = React.useState(42);
    const [align, setAlign]       = React.useState('center');
    const [ratioIdx, setRatioIdx] = React.useState(0);
    const [customC1, setCustomC1] = React.useState('#6366f1');
    const [customC2, setCustomC2] = React.useState('#ec4899');

    const canvasRef  = React.useRef(null);
    const previewRef = React.useRef(null);

    const bg    = BACKGROUNDS[bgIdx];
    const font  = FONTS[fontIdx];
    const ratio = RATIOS[ratioIdx];

    // Load selected Google Font
    React.useEffect(() => { ensureFont(font); }, [fontIdx]);

    // Draw the quote card on canvas whenever any input changes
    React.useEffect(() => {
      const timer = setTimeout(() => drawCard(), 120);
      return () => clearTimeout(timer);
    }, [quote, author, bgIdx, fontIdx, fontSize, align, ratioIdx, customC1, customC2]);

    function drawCard() {
      const c = canvasRef.current;
      if (!c) return;
      const W = ratio.w;
      const H = ratio.h;
      c.width = W;
      c.height = H;
      const ctx = c.getContext('2d');

      // --- Background gradient ---
      const g1 = bg.grad ? bg.grad[0] : customC1;
      const g2 = bg.grad ? bg.grad[1] : customC2;
      const grad = ctx.createLinearGradient(0, 0, W, H);
      grad.addColorStop(0, g1);
      grad.addColorStop(1, g2);
      ctx.fillStyle = grad;
      ctx.fillRect(0, 0, W, H);

      // --- Determine text color ---
      let textColor = bg.text;
      if (!bg.grad) {
        // For custom gradient, auto-detect white or black based on luminance
        const hex = customC1.replace('#', '');
        const r = parseInt(hex.substr(0, 2), 16);
        const g = parseInt(hex.substr(2, 2), 16);
        const b = parseInt(hex.substr(4, 2), 16);
        textColor = (r * 0.299 + g * 0.587 + b * 0.114) > 150 ? '#111111' : '#ffffff';
      }

      // --- Decorative quotation marks (large, semi-transparent) ---
      const quoteMarkSize = Math.round(W * 0.22);
      ctx.font = 'bold ' + quoteMarkSize + 'px Georgia, serif';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'top';
      ctx.fillStyle = textColor;
      ctx.globalAlpha = 0.08;
      ctx.fillText('\u201C', W * 0.18, H * 0.08);
      ctx.textBaseline = 'bottom';
      ctx.fillText('\u201D', W * 0.82, H * 0.92);
      ctx.globalAlpha = 1;

      // --- Quote text ---
      const scaledFont = Math.round(fontSize * (W / 1080));
      const fontFamily = "'" + font.value + "', Georgia, serif";
      ctx.font = '700 ' + scaledFont + 'px ' + fontFamily;
      ctx.textAlign = align;
      ctx.textBaseline = 'top';
      ctx.fillStyle = textColor;

      const pad = W * 0.12;
      const maxTextW = W - pad * 2;
      const lines = wrapText(ctx, quote, maxTextW);
      const lineH = scaledFont * 1.45;
      const totalTextH = lines.length * lineH;

      // Author line dimensions
      const authorFontSize = Math.round(scaledFont * 0.45);
      const authorH = author.trim() ? authorFontSize * 2.2 : 0;
      const blockH = totalTextH + authorH;

      const startY = (H - blockH) / 2;
      const textX = align === 'left' ? pad : align === 'right' ? W - pad : W / 2;

      for (let i = 0; i < lines.length; i++) {
        ctx.fillText(lines[i], textX, startY + i * lineH);
      }

      // --- Author line with em dash ---
      if (author.trim()) {
        ctx.font = '400 ' + authorFontSize + 'px ' + fontFamily;
        ctx.globalAlpha = 0.7;
        ctx.fillText('\u2014 ' + author, textX, startY + totalTextH + authorFontSize * 0.6);
        ctx.globalAlpha = 1;
      }

      // Update preview image
      if (previewRef.current) {
        previewRef.current.src = c.toDataURL('image/png');
      }
    }

    function handleDownload() {
      const c = canvasRef.current;
      if (!c) return;
      c.toBlob((blob) => {
        if (blob) window.downloadBlob(blob, 'quote-card.png');
      }, 'image/png');
    }

    // --- Gradient preview swatch ---
    function bgSwatchStyle(item, idx) {
      const g1 = item.grad ? item.grad[0] : customC1;
      const g2 = item.grad ? item.grad[1] : customC2;
      const isActive = bgIdx === idx;
      return {
        width: 48, height: 48, borderRadius: 8, cursor: 'pointer',
        background: 'linear-gradient(135deg, ' + g1 + ', ' + g2 + ')',
        border: isActive ? '2.5px solid var(--id-brand-blue)' : '2px solid var(--id-border)',
        boxShadow: isActive ? 'var(--id-shadow-focus)' : 'var(--id-shadow-xs)',
        flexShrink: 0,
        transition: 'border-color 0.15s, box-shadow 0.15s',
      };
    }

    const previewMaxW = 420;

    return (
      <div className="mini-tool">
        {/* Hidden full-resolution canvas */}
        <canvas ref={canvasRef} style={{ display: 'none' }} />

        {/* Live preview */}
        <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 20 }}>
          <div style={{
            width: '100%', maxWidth: previewMaxW,
            borderRadius: 12, overflow: 'hidden',
            boxShadow: 'var(--id-shadow-lg)',
            background: 'var(--id-surface-sunken)',
          }}>
            <img
              ref={previewRef}
              alt="Quote card preview"
              style={{
                display: 'block', width: '100%',
                aspectRatio: ratio.w + ' / ' + ratio.h,
                objectFit: 'contain',
              }}
            />
          </div>
        </div>

        {/* Quote text */}
        <div style={{ marginBottom: 12 }}>
          <label className="mini-label">Quote</label>
          <textarea
            className="mini-input"
            style={{ minHeight: 80, resize: 'vertical', width: '100%' }}
            value={quote}
            onChange={(e) => setQuote(e.target.value)}
            placeholder="Enter your quote..."
          />
        </div>

        {/* Author */}
        <div style={{ marginBottom: 16 }}>
          <label className="mini-label">Author (optional)</label>
          <input
            className="mini-input"
            style={{ width: '100%' }}
            value={author}
            onChange={(e) => setAuthor(e.target.value)}
            placeholder="Author name"
          />
        </div>

        {/* Background presets */}
        <div style={{ marginBottom: 16 }}>
          <label className="mini-label">Background</label>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
            {BACKGROUNDS.map((item, idx) => (
              <div key={item.label} style={{ textAlign: 'center' }}>
                <div
                  style={bgSwatchStyle(item, idx)}
                  title={item.label}
                  onClick={() => setBgIdx(idx)}
                />
                <div style={{
                  fontSize: 10, marginTop: 3,
                  color: bgIdx === idx ? 'var(--id-brand-blue)' : 'var(--id-text-subtle)',
                  fontWeight: bgIdx === idx ? 700 : 400,
                }}>{item.label}</div>
              </div>
            ))}
          </div>
          {/* Custom gradient color pickers */}
          {bgIdx === BACKGROUNDS.length - 1 && (
            <div className="mini-row" style={{ marginTop: 10, gridTemplateColumns: '1fr 1fr', maxWidth: 240 }}>
              <div className="mini-field">
                <label className="mini-label">Color 1</label>
                <input type="color" className="mini-input" value={customC1}
                       onChange={(e) => setCustomC1(e.target.value)}
                       style={{ height: 36, padding: 4 }} />
              </div>
              <div className="mini-field">
                <label className="mini-label">Color 2</label>
                <input type="color" className="mini-input" value={customC2}
                       onChange={(e) => setCustomC2(e.target.value)}
                       style={{ height: 36, padding: 4 }} />
              </div>
            </div>
          )}
        </div>

        {/* Font + Aspect Ratio row */}
        <div className="mini-row" style={{ gridTemplateColumns: '1fr 1fr', marginTop: 0 }}>
          <div className="mini-field">
            <label className="mini-label">Font</label>
            <select className="mini-input" value={fontIdx}
                    onChange={(e) => setFontIdx(Number(e.target.value))}>
              {FONTS.map((f, i) => (
                <option key={f.value} value={i}>{f.label}</option>
              ))}
            </select>
          </div>
          <div className="mini-field">
            <label className="mini-label">Aspect Ratio</label>
            <select className="mini-input" value={ratioIdx}
                    onChange={(e) => setRatioIdx(Number(e.target.value))}>
              {RATIOS.map((r, i) => (
                <option key={r.label} value={i}>{r.label} ({r.w}&times;{r.h})</option>
              ))}
            </select>
          </div>
        </div>

        {/* Font size slider */}
        <div className="cmp-slider-row" style={{ marginTop: 16 }}>
          <div className="cmp-label">
            <span>Font Size</span>
            <span className="val">{fontSize}px</span>
          </div>
          <input
            type="range" className="cmp-slider"
            min="24" max="64" step="1"
            value={fontSize}
            onChange={(e) => setFontSize(Number(e.target.value))}
          />
        </div>

        {/* Text alignment */}
        <div style={{ marginBottom: 16 }}>
          <label className="mini-label">Text Alignment</label>
          <div style={{ display: 'flex', gap: 6 }}>
            {ALIGNS.map((a) => {
              const active = align === a;
              return (
                <button
                  key={a}
                  className={active ? 'btn btn-primary' : 'btn btn-secondary'}
                  style={{ flex: 1, textTransform: 'capitalize', padding: '6px 0' }}
                  onClick={() => setAlign(a)}
                >
                  <window.Icon name="text" size={14} />
                  {' '}{a}
                </button>
              );
            })}
          </div>
        </div>

        {/* Download */}
        <div className="cmp-actions">
          <button className="btn btn-primary" onClick={handleDownload}>
            <window.Icon name="download" size={16} /> Download PNG
          </button>
        </div>
      </div>
    );
  };

})();
