// Code to Image — paste code, style it with themes and options, export as PNG.
// Renders everything on a canvas for pixel-perfect export without html2canvas.

window.TOOL_HANDLERS['code-to-image'] = function CodeToImageTool() {
  const THEMES = {
    dark:    { name: 'Dark',    bg: '#282a36', text: '#f8f8f2', lineNum: '#6272a4', accent: '#bd93f9', headerBg: '#21222c' },
    light:   { name: 'Light',   bg: '#fafafa', text: '#383a42', lineNum: '#a0a1a7', accent: '#4078f2', headerBg: '#eaeaeb' },
    dracula: { name: 'Dracula', bg: '#282a36', text: '#f8f8f2', lineNum: '#6272a4', accent: '#ff79c6', headerBg: '#21222c' },
    ocean:   { name: 'Ocean',   bg: '#1b2b34', text: '#d8dee9', lineNum: '#4f5b66', accent: '#6699cc', headerBg: '#152028' },
  };

  const GRADIENTS = [
    'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
    'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
    'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
    'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
    'linear-gradient(135deg, #fa709a 0%, #fee140 100%)',
    'linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%)',
  ];

  const PADDING_OPTIONS = [16, 32, 48, 64];

  const [code, setCode] = React.useState('function greet(name) {\n  const message = `Hello, ${name}!`;\n  console.log(message);\n  return message;\n}');
  const [theme, setTheme] = React.useState('dark');
  const [language, setLanguage] = React.useState('JavaScript');
  const [padding, setPadding] = React.useState(32);
  const [fontSize, setFontSize] = React.useState(14);
  const [borderRadius, setBorderRadius] = React.useState(8);
  const [showLineNumbers, setShowLineNumbers] = React.useState(true);
  const [showBackground, setShowBackground] = React.useState(true);
  const [showWindowControls, setShowWindowControls] = React.useState(true);
  const [gradientIndex, setGradientIndex] = React.useState(0);

  const previewRef = React.useRef(null);

  const t = THEMES[theme];
  const lines = code.split('\n');

  // Canvas export
  const exportPNG = () => {
    const scale = 2; // retina
    const fontFamily = '"JetBrains Mono", "SF Mono", "Fira Code", "Cascadia Code", Consolas, monospace';
    const lineHeight = fontSize * 1.55;
    const headerHeight = showWindowControls ? 36 : 0;
    const lineNumWidth = showLineNumbers ? (String(lines.length).length * fontSize * 0.65 + 20) : 0;

    // Measure max line width
    const measureCanvas = document.createElement('canvas');
    const mctx = measureCanvas.getContext('2d');
    mctx.font = `${fontSize}px ${fontFamily}`;
    let maxLineWidth = 0;
    lines.forEach((line) => {
      const w = mctx.measureText(line).width;
      if (w > maxLineWidth) maxLineWidth = w;
    });

    const codeWidth = lineNumWidth + maxLineWidth + 40;
    const codeHeight = lines.length * lineHeight + 24;
    const windowWidth = Math.max(codeWidth, 280);
    const windowHeight = headerHeight + codeHeight;

    const totalWidth = showBackground ? windowWidth + padding * 2 : windowWidth;
    const totalHeight = showBackground ? windowHeight + padding * 2 : windowHeight;

    const canvas = document.createElement('canvas');
    canvas.width = totalWidth * scale;
    canvas.height = totalHeight * scale;
    const ctx = canvas.getContext('2d');
    ctx.scale(scale, scale);

    // Background gradient
    if (showBackground) {
      const grad = GRADIENTS[gradientIndex];
      // Parse gradient colors
      const colorMatch = grad.match(/#[0-9a-f]{6}/gi);
      const angleMatch = grad.match(/(\d+)deg/);
      const angle = angleMatch ? parseInt(angleMatch[1]) * Math.PI / 180 : Math.PI / 4;
      if (colorMatch && colorMatch.length >= 2) {
        const gx0 = totalWidth / 2 - Math.cos(angle) * totalWidth / 2;
        const gy0 = totalHeight / 2 - Math.sin(angle) * totalHeight / 2;
        const gx1 = totalWidth / 2 + Math.cos(angle) * totalWidth / 2;
        const gy1 = totalHeight / 2 + Math.sin(angle) * totalHeight / 2;
        const g = ctx.createLinearGradient(gx0, gy0, gx1, gy1);
        g.addColorStop(0, colorMatch[0]);
        g.addColorStop(1, colorMatch[1]);
        ctx.fillStyle = g;
      } else {
        ctx.fillStyle = '#667eea';
      }
      ctx.fillRect(0, 0, totalWidth, totalHeight);
    }

    const ox = showBackground ? padding : 0;
    const oy = showBackground ? padding : 0;

    // Window shadow
    if (showBackground) {
      ctx.shadowColor = 'rgba(0,0,0,0.25)';
      ctx.shadowBlur = 20;
      ctx.shadowOffsetY = 8;
    }

    // Code window background
    ctx.fillStyle = t.bg;
    roundRect(ctx, ox, oy, windowWidth, windowHeight, borderRadius);
    ctx.fill();
    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    ctx.shadowOffsetY = 0;

    // Header
    if (showWindowControls) {
      ctx.fillStyle = t.headerBg;
      roundRectTop(ctx, ox, oy, windowWidth, headerHeight, borderRadius);
      ctx.fill();

      // Window dots
      const dotY = oy + headerHeight / 2;
      const dotStartX = ox + 16;
      const dotR = 6;
      ['#ff5f57', '#febc2e', '#28c840'].forEach((c, i) => {
        ctx.fillStyle = c;
        ctx.beginPath();
        ctx.arc(dotStartX + i * 20, dotY, dotR, 0, Math.PI * 2);
        ctx.fill();
      });

      // Language label
      if (language) {
        ctx.fillStyle = t.lineNum;
        ctx.font = `500 ${fontSize * 0.85}px ${fontFamily}`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText(language, ox + windowWidth / 2, dotY);
        ctx.textAlign = 'left';
      }

      // Separator line
      ctx.fillStyle = t.bg;
      ctx.fillRect(ox, oy + headerHeight - 1, windowWidth, 1);
    }

    // Code lines
    const codeStartY = oy + headerHeight + 16;
    ctx.font = `${fontSize}px ${fontFamily}`;
    ctx.textBaseline = 'top';

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

      // Line number
      if (showLineNumbers) {
        ctx.fillStyle = t.lineNum;
        ctx.textAlign = 'right';
        ctx.fillText(String(i + 1), ox + lineNumWidth - 8, ly);
        ctx.textAlign = 'left';
      }

      // Code text
      ctx.fillStyle = t.text;
      ctx.fillText(line, ox + lineNumWidth + 8, ly);
    });

    canvas.toBlob((blob) => {
      if (blob) window.downloadBlob(blob, 'code-snapshot.png');
    }, 'image/png');
    window.mmTrackComplete?.('code-to-image', { success: true });
  };

  function roundRect(ctx, x, y, w, h, r) {
    ctx.beginPath();
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + w - r, y);
    ctx.quadraticCurveTo(x + w, y, x + w, y + r);
    ctx.lineTo(x + w, y + h - r);
    ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
    ctx.lineTo(x + r, y + h);
    ctx.quadraticCurveTo(x, y + h, x, y + h - r);
    ctx.lineTo(x, y + r);
    ctx.quadraticCurveTo(x, y, x + r, y);
    ctx.closePath();
  }

  function roundRectTop(ctx, x, y, w, h, r) {
    ctx.beginPath();
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + w - r, y);
    ctx.quadraticCurveTo(x + w, y, x + w, y + r);
    ctx.lineTo(x + w, y + h);
    ctx.lineTo(x, y + h);
    ctx.lineTo(x, y + r);
    ctx.quadraticCurveTo(x, y, x + r, y);
    ctx.closePath();
  }

  return (
    <div className="mini-tool">
      <style>{`
        .c2i-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
        .c2i-controls { display: flex; flex-direction: column; gap: 14px; }
        .c2i-textarea {
          font-family: 'JetBrains Mono', monospace; font-size: 13px;
          min-height: 160px; resize: vertical; line-height: 1.5;
          background: var(--id-surface-alt); color: var(--id-text);
          border: 1px solid var(--id-border); border-radius: 8px;
          padding: 12px; width: 100%; box-sizing: border-box;
        }
        .c2i-textarea:focus { border-color: var(--id-brand-blue); outline: none; box-shadow: var(--id-shadow-focus); }
        .c2i-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
        .c2i-row3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
        .c2i-toggle-row {
          display: flex; align-items: center; justify-content: space-between;
          padding: 6px 0; border-bottom: 1px solid var(--id-border);
        }
        .c2i-toggle-label { font-size: 13px; color: var(--id-text); font-weight: 500; }
        .c2i-toggle {
          position: relative; width: 38px; height: 22px; cursor: pointer;
          background: var(--id-border-strong); border-radius: 11px;
          border: none; transition: background 180ms ease;
        }
        .c2i-toggle.on { background: var(--id-brand-blue); }
        .c2i-toggle::after {
          content: ''; position: absolute; width: 16px; height: 16px;
          border-radius: 50%; background: white; top: 3px; left: 3px;
          transition: transform 180ms ease;
        }
        .c2i-toggle.on::after { transform: translateX(16px); }
        .c2i-preview-wrap {
          border-radius: 10px; overflow: hidden;
          border: 1px solid var(--id-border); background: #1a1a2e;
        }
        .c2i-preview-outer {
          padding: 0; display: flex; align-items: center; justify-content: center;
          overflow: auto; max-height: 450px;
        }
        .c2i-grad-row { display: flex; gap: 6px; flex-wrap: wrap; }
        .c2i-grad-swatch {
          width: 28px; height: 28px; border-radius: 6px; cursor: pointer;
          border: 2px solid transparent; transition: border-color 180ms ease;
        }
        .c2i-grad-swatch.active { border-color: var(--id-brand-blue); }
        @media (max-width: 700px) {
          .c2i-layout { grid-template-columns: 1fr; }
        }
      `}</style>

      <div className="c2i-layout">
        {/* Left: controls */}
        <div className="c2i-controls">
          <div>
            <label className="mini-label">Code</label>
            <textarea className="c2i-textarea" value={code}
                      onChange={(e) => setCode(e.target.value)}
                      placeholder="Paste your code here..." spellCheck="false" />
          </div>

          <div className="c2i-row">
            <div className="mini-field">
              <label className="mini-label">Theme</label>
              <select className="mini-input" value={theme} onChange={(e) => setTheme(e.target.value)}>
                {Object.entries(THEMES).map(([k, v]) => (
                  <option key={k} value={k}>{v.name}</option>
                ))}
              </select>
            </div>
            <div className="mini-field">
              <label className="mini-label">Language label</label>
              <input className="mini-input" value={language}
                     onChange={(e) => setLanguage(e.target.value)}
                     placeholder="e.g. JavaScript" />
            </div>
          </div>

          <div className="c2i-row3">
            <div className="mini-field">
              <label className="mini-label">Padding</label>
              <select className="mini-input" value={padding} onChange={(e) => setPadding(Number(e.target.value))}>
                {PADDING_OPTIONS.map((p) => (
                  <option key={p} value={p}>{p}px</option>
                ))}
              </select>
            </div>
            <div className="mini-field">
              <label className="mini-label">Font size</label>
              <input type="number" className="mini-input" min="12" max="20" value={fontSize}
                     onChange={(e) => setFontSize(Math.max(12, Math.min(20, Number(e.target.value) || 14)))} />
            </div>
            <div className="mini-field">
              <label className="mini-label">Radius</label>
              <input type="number" className="mini-input" min="0" max="16" value={borderRadius}
                     onChange={(e) => setBorderRadius(Math.max(0, Math.min(16, Number(e.target.value) || 0)))} />
            </div>
          </div>

          <div>
            <div className="c2i-toggle-row">
              <span className="c2i-toggle-label">Line numbers</span>
              <button className={`c2i-toggle ${showLineNumbers ? 'on' : ''}`}
                      onClick={() => setShowLineNumbers(!showLineNumbers)} />
            </div>
            <div className="c2i-toggle-row">
              <span className="c2i-toggle-label">Window controls</span>
              <button className={`c2i-toggle ${showWindowControls ? 'on' : ''}`}
                      onClick={() => setShowWindowControls(!showWindowControls)} />
            </div>
            <div className="c2i-toggle-row" style={{ borderBottom: 'none' }}>
              <span className="c2i-toggle-label">Background</span>
              <button className={`c2i-toggle ${showBackground ? 'on' : ''}`}
                      onClick={() => setShowBackground(!showBackground)} />
            </div>
          </div>

          {showBackground && (
            <div>
              <label className="mini-label">Gradient</label>
              <div className="c2i-grad-row">
                {GRADIENTS.map((g, i) => (
                  <div key={i} className={`c2i-grad-swatch ${gradientIndex === i ? 'active' : ''}`}
                       style={{ background: g }}
                       onClick={() => setGradientIndex(i)} />
                ))}
              </div>
            </div>
          )}
        </div>

        {/* Right: preview */}
        <div>
          <label className="mini-label">Preview</label>
          <div className="c2i-preview-wrap">
            <div className="c2i-preview-outer"
                 style={{ background: showBackground ? GRADIENTS[gradientIndex] : 'transparent',
                          padding: showBackground ? padding : 0 }}>
              <div ref={previewRef} style={{
                background: t.bg, borderRadius: borderRadius,
                overflow: 'hidden', width: '100%', maxWidth: 600,
                boxShadow: showBackground ? '0 8px 24px rgba(0,0,0,0.25)' : 'none',
              }}>
                {/* Header */}
                {showWindowControls && (
                  <div style={{
                    background: t.headerBg, padding: '10px 16px',
                    display: 'flex', alignItems: 'center', position: 'relative',
                  }}>
                    <div style={{ display: 'flex', gap: 7 }}>
                      {['#ff5f57', '#febc2e', '#28c840'].map((c) => (
                        <div key={c} style={{
                          width: 12, height: 12, borderRadius: '50%', background: c,
                        }} />
                      ))}
                    </div>
                    {language && (
                      <div style={{
                        position: 'absolute', left: '50%', transform: 'translateX(-50%)',
                        fontSize: fontSize * 0.85, color: t.lineNum,
                        fontFamily: "'JetBrains Mono', monospace", fontWeight: 500,
                      }}>{language}</div>
                    )}
                  </div>
                )}

                {/* Code body */}
                <div style={{ padding: '12px 16px', overflow: 'auto' }}>
                  <pre style={{
                    margin: 0, fontFamily: "'JetBrains Mono', monospace",
                    fontSize: fontSize, lineHeight: 1.55, color: t.text,
                  }}>
                    {lines.map((line, i) => (
                      <div key={i} style={{ display: 'flex', minHeight: fontSize * 1.55 }}>
                        {showLineNumbers && (
                          <span style={{
                            color: t.lineNum, userSelect: 'none', textAlign: 'right',
                            minWidth: String(lines.length).length * fontSize * 0.65 + 8,
                            paddingRight: 12, flexShrink: 0,
                          }}>{i + 1}</span>
                        )}
                        <span style={{ whiteSpace: 'pre' }}>{line || ' '}</span>
                      </div>
                    ))}
                  </pre>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div className="cmp-actions">
        <button className="btn btn-primary" onClick={exportPNG} disabled={!code.trim()}>
          <window.Icon name="download" size={16} /> Export PNG
        </button>
      </div>
    </div>
  );
};
