// YouTube Thumbnail Maker — canvas-based 1280x720 creator with drag-to-position text.

(function () {
  const FONTS = ['Oswald', 'Bebas Neue', 'Anton', 'Roboto Condensed', 'Poppins', 'Montserrat'];
  if (!document.querySelector('[data-yt-thumb-fonts]')) {
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.dataset.ytThumbFonts = '1';
    link.href = 'https://fonts.googleapis.com/css2?' +
      FONTS.map(f => f.replace(/ /g, '+') + ':wght@400;700;900').join('&family=') + '&display=swap';
    document.head.appendChild(link);
  }

  const W = 1280, H = 720;

  const GRADIENT_PRESETS = [
    { name: 'Sunset',  from: '#ff512f', to: '#dd2476' },
    { name: 'Ocean',   from: '#2193b0', to: '#6dd5ed' },
    { name: 'Lime',    from: '#56ab2f', to: '#a8e063' },
    { name: 'Night',   from: '#0f0c29', to: '#302b63' },
    { name: 'Fire',    from: '#f12711', to: '#f5af19' },
    { name: 'Royal',   from: '#141e30', to: '#243b55' },
    { name: 'Candy',   from: '#fc5c7d', to: '#6a82fb' },
    { name: 'Emerald', from: '#11998e', to: '#38ef7d' },
  ];

  const POS_PRESETS = [
    { label: 'Center',       x: 0.5,  y: 0.5  },
    { label: 'Top Left',     x: 0.15, y: 0.18 },
    { label: 'Top Center',   x: 0.5,  y: 0.18 },
    { label: 'Top Right',    x: 0.85, y: 0.18 },
    { label: 'Bottom Left',  x: 0.15, y: 0.82 },
    { label: 'Bottom Center',x: 0.5,  y: 0.82 },
    { label: 'Bottom Right', x: 0.85, y: 0.82 },
  ];

  window.TOOL_HANDLERS['yt-thumbnail'] = function YtThumbnailTool() {
    const { useState, useRef, useCallback, useEffect } = React;

    // Background
    const [bgMode, setBgMode] = useState('gradient');
    const [bgColor, setBgColor] = useState('#1a1a2e');
    const [gradientIdx, setGradientIdx] = useState(0);
    const [bgImg, setBgImg] = useState(null);
    const [bgBrightness, setBgBrightness] = useState(80);
    const [bgBlur, setBgBlur] = useState(0);
    const [overlayOpacity, setOverlayOpacity] = useState(0);
    const [overlayColor, setOverlayColor] = useState('#000000');

    // Headline
    const [headline, setHeadline] = useState('YOUR TITLE HERE');
    const [headlineSize, setHeadlineSize] = useState(72);
    const [headlineColor, setHeadlineColor] = useState('#ffffff');
    const [headlineStroke, setHeadlineStroke] = useState(true);
    const [headlineStrokeColor, setHeadlineStrokeColor] = useState('#000000');
    const [headlineFont, setHeadlineFont] = useState('Oswald');
    const [headlineShadow, setHeadlineShadow] = useState(true);
    // Position as 0-1 values — draggable
    const [posX, setPosX] = useState(0.5);
    const [posY, setPosY] = useState(0.5);

    // Subtitle
    const [subtitle, setSubtitle] = useState('');
    const [subtitleSize, setSubtitleSize] = useState(32);
    const [subtitleColor, setSubtitleColor] = useState('#ffffffcc');

    const canvasRef = useRef(null);
    const dragging = useRef(false);

    const handleBgFile = async (f) => {
      if (!f || !f.type.startsWith('image/')) return;
      const { img } = await window.loadImageFromFile(f);
      setBgImg(img); setBgMode('image');
    };

    // Word-wrap helper
    function wrapText(ctx, text, maxWidth) {
      const words = text.split(' ');
      const lines = []; let cur = '';
      for (const word of words) {
        const test = cur ? cur + ' ' + word : word;
        if (ctx.measureText(test).width > maxWidth && cur) { lines.push(cur); cur = word; }
        else cur = test;
      }
      if (cur) lines.push(cur);
      return lines.length ? lines : [''];
    }

    // Draw
    const draw = useCallback(() => {
      const canvas = canvasRef.current;
      if (!canvas) return;
      canvas.width = W; canvas.height = H;
      const ctx = canvas.getContext('2d');

      // Background
      if (bgMode === 'solid') {
        ctx.fillStyle = bgColor; ctx.fillRect(0, 0, W, H);
      } else if (bgMode === 'gradient') {
        const g = GRADIENT_PRESETS[gradientIdx] || GRADIENT_PRESETS[0];
        const grad = ctx.createLinearGradient(0, 0, W, H);
        grad.addColorStop(0, g.from); grad.addColorStop(1, g.to);
        ctx.fillStyle = grad; ctx.fillRect(0, 0, W, H);
      } else if (bgMode === 'image' && bgImg) {
        const off = document.createElement('canvas');
        off.width = W; off.height = H;
        const octx = off.getContext('2d');
        const filters = [];
        if (bgBrightness !== 100) filters.push('brightness(' + bgBrightness + '%)');
        if (bgBlur > 0) filters.push('blur(' + bgBlur + 'px)');
        octx.filter = filters.length ? filters.join(' ') : 'none';
        const scale = Math.max(W / bgImg.width, H / bgImg.height);
        const iw = bgImg.width * scale, ih = bgImg.height * scale;
        octx.drawImage(bgImg, (W - iw) / 2, (H - ih) / 2, iw, ih);
        ctx.drawImage(off, 0, 0);
      }

      // Overlay
      if (overlayOpacity > 0) {
        ctx.fillStyle = overlayColor;
        ctx.globalAlpha = overlayOpacity / 100;
        ctx.fillRect(0, 0, W, H);
        ctx.globalAlpha = 1;
      }

      // Text position
      const tx = posX * W;
      const ty = posY * H;
      let align = 'center';
      if (posX < 0.3) align = 'left';
      else if (posX > 0.7) align = 'right';
      ctx.textAlign = align;

      // Headline
      if (headline) {
        ctx.font = '900 ' + headlineSize + 'px "' + headlineFont + '", sans-serif';
        ctx.textBaseline = 'middle';
        ctx.lineJoin = 'round';

        const maxW = W * 0.85;
        const lines = wrapText(ctx, headline.toUpperCase(), maxW);
        const lineH = headlineSize * 1.15;
        const totalH = lineH * lines.length;
        const startY = ty - totalH / 2 + lineH / 2;

        lines.forEach((line, i) => {
          const ly = startY + i * lineH;

          // Shadow
          if (headlineShadow) {
            ctx.shadowColor = 'rgba(0,0,0,0.6)';
            ctx.shadowBlur = 12;
            ctx.shadowOffsetX = 4;
            ctx.shadowOffsetY = 4;
          }

          // Stroke
          if (headlineStroke) {
            ctx.strokeStyle = headlineStrokeColor;
            ctx.lineWidth = Math.max(4, headlineSize / 12);
            ctx.strokeText(line, tx, ly);
          }

          ctx.fillStyle = headlineColor;
          ctx.fillText(line, tx, ly);

          // Reset shadow
          ctx.shadowColor = 'transparent';
          ctx.shadowBlur = 0;
          ctx.shadowOffsetX = 0;
          ctx.shadowOffsetY = 0;
        });

        // Subtitle
        if (subtitle) {
          ctx.font = '700 ' + subtitleSize + 'px "' + headlineFont + '", sans-serif';
          ctx.fillStyle = subtitleColor;
          const subLines = wrapText(ctx, subtitle, maxW);
          const subLineH = subtitleSize * 1.2;
          const subStartY = startY + totalH + subtitleSize * 0.4;
          subLines.forEach((line, i) => {
            if (headlineShadow) {
              ctx.shadowColor = 'rgba(0,0,0,0.4)';
              ctx.shadowBlur = 8;
              ctx.shadowOffsetX = 2;
              ctx.shadowOffsetY = 2;
            }
            ctx.fillText(line, tx, subStartY + i * subLineH);
            ctx.shadowColor = 'transparent';
          });
        }
      }

      // Draw drag crosshair hint (subtle)
      ctx.strokeStyle = 'rgba(255,255,255,0.3)';
      ctx.lineWidth = 1;
      ctx.setLineDash([6, 4]);
      ctx.beginPath(); ctx.moveTo(tx, ty - 15); ctx.lineTo(tx, ty + 15); ctx.stroke();
      ctx.beginPath(); ctx.moveTo(tx - 15, ty); ctx.lineTo(tx + 15, ty); ctx.stroke();
      ctx.setLineDash([]);
    }, [bgMode, bgColor, gradientIdx, bgImg, bgBrightness, bgBlur, overlayOpacity, overlayColor,
        headline, headlineSize, headlineColor, headlineStroke, headlineStrokeColor,
        headlineFont, headlineShadow, posX, posY, subtitle, subtitleSize, subtitleColor]);

    useEffect(() => {
      const id = setTimeout(draw, 50);
      return () => clearTimeout(id);
    }, [draw]);

    useEffect(() => {
      if (document.fonts && document.fonts.ready) document.fonts.ready.then(draw);
    }, [draw]);

    // Drag handlers on canvas
    const getCanvasPos = (e) => {
      const rect = canvasRef.current.getBoundingClientRect();
      const clientX = e.touches ? e.touches[0].clientX : e.clientX;
      const clientY = e.touches ? e.touches[0].clientY : e.clientY;
      return {
        x: Math.max(0.05, Math.min(0.95, (clientX - rect.left) / rect.width)),
        y: Math.max(0.05, Math.min(0.95, (clientY - rect.top) / rect.height)),
      };
    };

    const onDown = (e) => {
      dragging.current = true;
      const pos = getCanvasPos(e);
      setPosX(pos.x); setPosY(pos.y);
    };
    const onMove = (e) => {
      if (!dragging.current) return;
      e.preventDefault();
      const pos = getCanvasPos(e);
      setPosX(pos.x); setPosY(pos.y);
    };
    const onUp = () => { dragging.current = false; };

    useEffect(() => {
      document.addEventListener('mouseup', onUp);
      document.addEventListener('touchend', onUp);
      return () => { document.removeEventListener('mouseup', onUp); document.removeEventListener('touchend', onUp); };
    }, []);

    const downloadPng = () => {
      const canvas = canvasRef.current;
      if (!canvas) return;
      // Redraw without crosshair
      draw();
      canvas.toBlob((blob) => { if (blob) window.downloadBlob(blob, 'thumbnail.png'); }, 'image/png');
    };

    return (
      <div className="mini-tool">
        {/* Canvas — draggable */}
        <div style={{ marginBottom: 16 }}>
          <div style={{
            borderRadius: 10, overflow: 'hidden', border: '1px solid var(--id-border)', background: '#000',
            cursor: 'crosshair', touchAction: 'none',
          }}>
            <canvas ref={canvasRef} style={{ width: '100%', height: 'auto', display: 'block' }}
              onMouseDown={onDown} onMouseMove={onMove}
              onTouchStart={onDown} onTouchMove={onMove} />
          </div>
          <div className="cmp-meta" style={{ marginTop: 6, textAlign: 'center' }}>
            {W}×{H}px · Drag on canvas to position text
          </div>
        </div>

        {/* Quick position presets */}
        <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap', marginBottom: 14 }}>
          {POS_PRESETS.map((p) => (
            <button key={p.label} className="filter-pill" style={{ fontSize: 11, padding: '3px 8px' }}
              onClick={() => { setPosX(p.x); setPosY(p.y); }}>
              {p.label}
            </button>
          ))}
        </div>

        {/* Background */}
        <div style={{ marginBottom: 14 }}>
          <label className="mini-label">Background</label>
          <div style={{ display: 'flex', gap: 6, marginBottom: 8 }}>
            {['solid', 'gradient', 'image'].map(m => (
              <button key={m} className={'filter-pill' + (bgMode === m ? ' active' : '')}
                onClick={() => setBgMode(m)}>{m.charAt(0).toUpperCase() + m.slice(1)}</button>
            ))}
          </div>

          {bgMode === 'solid' && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <input type="color" value={bgColor} onChange={(e) => setBgColor(e.target.value)}
                style={{ width: 36, height: 30, border: 'none', cursor: 'pointer', borderRadius: 6 }} />
              <input className="mini-input" value={bgColor} onChange={(e) => setBgColor(e.target.value)} style={{ width: 90 }} />
            </div>
          )}

          {bgMode === 'gradient' && (
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
              {GRADIENT_PRESETS.map((g, i) => (
                <button key={i} onClick={() => setGradientIdx(i)} title={g.name} style={{
                  width: 44, height: 28, borderRadius: 8, cursor: 'pointer',
                  border: i === gradientIdx ? '2px solid var(--id-brand-blue)' : '2px solid var(--id-border)',
                  background: 'linear-gradient(135deg, ' + g.from + ', ' + g.to + ')',
                }} />
              ))}
            </div>
          )}

          {bgMode === 'image' && (
            !bgImg ? (
              <window.Dropzone onFile={handleBgFile} title="Drop background image" hint="JPG, PNG, WebP" accept="image/*" />
            ) : (
              <div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
                  <div>
                    <label className="mini-label">Brightness: {bgBrightness}%</label>
                    <input type="range" className="cmp-slider" min="20" max="150" value={bgBrightness} onChange={(e) => setBgBrightness(+e.target.value)} />
                  </div>
                  <div>
                    <label className="mini-label">Blur: {bgBlur}px</label>
                    <input type="range" className="cmp-slider" min="0" max="20" value={bgBlur} onChange={(e) => setBgBlur(+e.target.value)} />
                  </div>
                </div>
                <button className="btn btn-secondary" style={{ marginTop: 6 }} onClick={() => setBgImg(null)}>
                  <window.Icon name="upload" size={14} /> Change image
                </button>
              </div>
            )
          )}
        </div>

        {/* Overlay */}
        {bgMode === 'image' && bgImg && (
          <div style={{ marginBottom: 14 }}>
            <label className="mini-label">Color Overlay: {overlayOpacity}%</label>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <input type="color" value={overlayColor} onChange={(e) => setOverlayColor(e.target.value)}
                style={{ width: 30, height: 24, border: 'none', cursor: 'pointer', borderRadius: 4 }} />
              <input type="range" className="cmp-slider" style={{ flex: 1 }} min="0" max="80" value={overlayOpacity}
                onChange={(e) => setOverlayOpacity(+e.target.value)} />
            </div>
          </div>
        )}

        {/* Headline */}
        <div style={{ marginBottom: 14 }}>
          <label className="mini-label">Headline</label>
          <input className="mini-input" value={headline} onChange={(e) => setHeadline(e.target.value)}
            placeholder="YOUR TITLE HERE" style={{ width: '100%', marginBottom: 8 }} />

          <div className="mini-row" style={{ gap: 10 }}>
            <div className="mini-field">
              <label className="mini-label">Font</label>
              <select className="mini-input" value={headlineFont} onChange={(e) => setHeadlineFont(e.target.value)}>
                {FONTS.map(f => <option key={f} value={f} style={{ fontFamily: f }}>{f}</option>)}
              </select>
            </div>
            <div className="mini-field">
              <label className="mini-label">Size: {headlineSize}px</label>
              <input type="range" className="cmp-slider" min="32" max="140" value={headlineSize}
                onChange={(e) => setHeadlineSize(+e.target.value)} />
            </div>
          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 6, flexWrap: 'wrap' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
              <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--id-text-muted)' }}>Fill</span>
              <input type="color" value={headlineColor} onChange={(e) => setHeadlineColor(e.target.value)}
                style={{ width: 28, height: 22, border: 'none', cursor: 'pointer', borderRadius: 4 }} />
            </div>
            <label style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 11, fontWeight: 600, color: 'var(--id-text-muted)', cursor: 'pointer' }}>
              <input type="checkbox" checked={headlineStroke} onChange={(e) => setHeadlineStroke(e.target.checked)} /> Stroke
            </label>
            {headlineStroke && (
              <input type="color" value={headlineStrokeColor} onChange={(e) => setHeadlineStrokeColor(e.target.value)}
                style={{ width: 28, height: 22, border: 'none', cursor: 'pointer', borderRadius: 4 }} />
            )}
            <label style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 11, fontWeight: 600, color: 'var(--id-text-muted)', cursor: 'pointer' }}>
              <input type="checkbox" checked={headlineShadow} onChange={(e) => setHeadlineShadow(e.target.checked)} /> Shadow
            </label>
          </div>
        </div>

        {/* Subtitle */}
        <div style={{ marginBottom: 14 }}>
          <label className="mini-label">Subtitle (optional)</label>
          <input className="mini-input" value={subtitle} onChange={(e) => setSubtitle(e.target.value)}
            placeholder="Add a subtitle..." style={{ width: '100%' }} />
          {subtitle && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 6 }}>
              <div style={{ flex: 1 }}>
                <label className="mini-label">Size: {subtitleSize}px</label>
                <input type="range" className="cmp-slider" min="18" max="60" value={subtitleSize} onChange={(e) => setSubtitleSize(+e.target.value)} />
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--id-text-muted)' }}>Color</span>
                <input type="color" value={subtitleColor.slice(0, 7)} onChange={(e) => setSubtitleColor(e.target.value)}
                  style={{ width: 28, height: 22, border: 'none', cursor: 'pointer', borderRadius: 4 }} />
              </div>
            </div>
          )}
        </div>

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