// Barcode Generator — generate barcodes in various formats via JsBarcode (CDN).
// Renders to SVG with configurable format, colors, bar width, height, and text display.
// Output is downloadable as PNG or SVG.

const JSBARCODE_URL = 'https://cdn.jsdelivr.net/npm/jsbarcode@3.11.6/dist/JsBarcode.all.min.js';

window.TOOL_HANDLERS['barcode-generator'] = function BarcodeGeneratorTool() {
  const [ready, setReady] = React.useState(false);
  const [loadErr, setLoadErr] = React.useState('');
  const [value, setValue] = React.useState('1234567890');
  const [format, setFormat] = React.useState('CODE128');
  const [barWidth, setBarWidth] = React.useState(2);
  const [height, setHeight] = React.useState(100);
  const [displayValue, setDisplayValue] = React.useState(true);
  const [bg, setBg] = React.useState('#ffffff');
  const [lineColor, setLineColor] = React.useState('#000000');
  const [err, setErr] = React.useState('');
  const [copied, setCopied] = React.useState(false);
  const svgRef = React.useRef(null);

  const FORMATS = [
    { value: 'CODE128', label: 'CODE128' },
    { value: 'EAN13', label: 'EAN-13' },
    { value: 'EAN8', label: 'EAN-8' },
    { value: 'UPC', label: 'UPC-A' },
    { value: 'CODE39', label: 'CODE39' },
    { value: 'ITF14', label: 'ITF-14' },
    { value: 'MSI', label: 'MSI' },
    { value: 'pharmacode', label: 'Pharmacode' },
  ];

  // Load JsBarcode on mount
  React.useEffect(function () {
    window.loadScript(JSBARCODE_URL)
      .then(function () { setReady(true); })
      .catch(function (e) { setLoadErr(e.message || 'Failed to load JsBarcode library'); });
  }, []);

  // Render barcode whenever inputs change
  React.useEffect(function () {
    if (!ready || !svgRef.current) return;
    setErr('');
    if (!value.trim()) {
      svgRef.current.innerHTML = '';
      return;
    }
    try {
      window.JsBarcode(svgRef.current, value, {
        format: format,
        width: barWidth,
        height: height,
        displayValue: displayValue,
        background: bg,
        lineColor: lineColor,
        margin: 10,
        fontSize: 16,
        textMargin: 4,
      });
    } catch (e) {
      svgRef.current.innerHTML = '';
      var msg = e.message || String(e);
      // Provide friendly messages for common validation errors
      if (format === 'EAN13') {
        setErr('EAN-13 requires exactly 12 or 13 digits (0-9).');
      } else if (format === 'EAN8') {
        setErr('EAN-8 requires exactly 7 or 8 digits (0-9).');
      } else if (format === 'UPC') {
        setErr('UPC-A requires exactly 11 or 12 digits (0-9).');
      } else if (format === 'ITF14') {
        setErr('ITF-14 requires exactly 13 or 14 digits (0-9).');
      } else if (format === 'pharmacode') {
        setErr('Pharmacode requires a number between 3 and 131070.');
      } else if (format === 'MSI') {
        setErr('MSI requires only digits (0-9).');
      } else {
        setErr(msg);
      }
    }
  }, [ready, value, format, barWidth, height, displayValue, bg, lineColor]);

  var getSvgString = function () {
    if (!svgRef.current) return null;
    var serializer = new XMLSerializer();
    return serializer.serializeToString(svgRef.current);
  };

  var downloadPng = function () {
    var svgEl = svgRef.current;
    if (!svgEl) return;
    var svgStr = getSvgString();
    if (!svgStr) return;
    var svgBlob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });
    var url = URL.createObjectURL(svgBlob);
    var img = new Image();
    img.onload = function () {
      var canvas = document.createElement('canvas');
      canvas.width = svgEl.width.baseVal.value || svgEl.getBoundingClientRect().width;
      canvas.height = svgEl.height.baseVal.value || svgEl.getBoundingClientRect().height;
      var ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0);
      URL.revokeObjectURL(url);
      canvas.toBlob(function (blob) {
        if (blob) window.downloadBlob(blob, 'barcode.png');
      }, 'image/png');
    };
    img.onerror = function () { URL.revokeObjectURL(url); };
    img.src = url;
    window.mmTrackComplete && window.mmTrackComplete('barcode-generator', { success: true, format: 'png' });
  };

  var downloadSvg = function () {
    var svgStr = getSvgString();
    if (!svgStr) return;
    var blob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });
    window.downloadBlob(blob, 'barcode.svg');
    window.mmTrackComplete && window.mmTrackComplete('barcode-generator', { success: true, format: 'svg' });
  };

  var copySvg = function () {
    var svgStr = getSvgString();
    if (!svgStr) return;
    navigator.clipboard.writeText(svgStr).then(function () {
      setCopied(true);
      setTimeout(function () { setCopied(false); }, 2000);
    }).catch(function () {
      // Fallback: select from a temporary textarea
      var ta = document.createElement('textarea');
      ta.value = svgStr;
      document.body.appendChild(ta);
      ta.select();
      document.execCommand('copy');
      document.body.removeChild(ta);
      setCopied(true);
      setTimeout(function () { setCopied(false); }, 2000);
    });
  };

  if (loadErr) return <window.ToolError error={loadErr} hint="Could not load the barcode library from CDN." />;
  if (!ready) return <window.LoadingCard label="Loading barcode library..." sub="JsBarcode from CDN" />;

  var hasBarcode = !err && value.trim();

  return (
    <div className="mini-tool">
      <div className="cmp-preview" style={{ gridTemplateColumns: '1fr 1fr', alignItems: 'start', gap: 20 }}>
        {/* Left column: controls */}
        <div>
          <label className="mini-label">Barcode value</label>
          <input
            className="mini-input"
            type="text"
            value={value}
            onChange={function (e) { setValue(e.target.value); }}
            placeholder="Enter text or numbers"
          />

          <label className="mini-label" style={{ marginTop: 14 }}>Format</label>
          <select className="mini-input" value={format} onChange={function (e) { setFormat(e.target.value); }}>
            {FORMATS.map(function (f) {
              return <option key={f.value} value={f.value}>{f.label}</option>;
            })}
          </select>

          <div className="mini-row" style={{ marginTop: 14 }}>
            <div className="mini-field" style={{ flex: 1 }}>
              <label className="mini-label">Bar width</label>
              <input type="number" className="mini-input" min="1" max="4" step="1"
                     value={barWidth}
                     onChange={function (e) { setBarWidth(Math.max(1, Math.min(4, Number(e.target.value) || 2))); }} />
            </div>
            <div className="mini-field" style={{ flex: 1 }}>
              <label className="mini-label">Height (px)</label>
              <input type="number" className="mini-input" min="50" max="200" step="10"
                     value={height}
                     onChange={function (e) { setHeight(Math.max(50, Math.min(200, Number(e.target.value) || 100))); }} />
            </div>
          </div>

          <div className="mini-row" style={{ marginTop: 14 }}>
            <div className="mini-field" style={{ flex: 1 }}>
              <label className="mini-label">Line color</label>
              <input type="color" className="mini-input" value={lineColor}
                     onChange={function (e) { setLineColor(e.target.value); }}
                     style={{ height: 36, padding: 4 }} />
            </div>
            <div className="mini-field" style={{ flex: 1 }}>
              <label className="mini-label">Background</label>
              <input type="color" className="mini-input" value={bg}
                     onChange={function (e) { setBg(e.target.value); }}
                     style={{ height: 36, padding: 4 }} />
            </div>
          </div>

          <div className="mini-row" style={{ marginTop: 14, alignItems: 'center' }}>
            <label className="mini-label" style={{ marginBottom: 0, cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 8 }}>
              <input type="checkbox" checked={displayValue}
                     onChange={function (e) { setDisplayValue(e.target.checked); }}
                     style={{ width: 18, height: 18 }} />
              Show text below barcode
            </label>
          </div>

          {err && (
            <div style={{ color: '#c8321f', marginTop: 12, padding: '8px 12px', background: 'rgba(200,50,31,0.08)', borderRadius: 8, fontSize: 13 }}>
              <window.Icon name="x" size={14} style={{ verticalAlign: -2, marginRight: 4 }} /> {err}
            </div>
          )}

          <div className="cmp-meta" style={{ marginTop: 12 }}>
            CODE128 accepts any text. EAN/UPC/ITF-14 require specific digit counts. Pharmacode encodes numbers 3-131070.
          </div>
        </div>

        {/* Right column: preview */}
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
          <div style={{
            background: bg,
            padding: 16,
            borderRadius: 10,
            boxShadow: 'var(--id-shadow-md)',
            minHeight: 100,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
          }}>
            <svg ref={svgRef} style={{ display: 'block', maxWidth: '100%', height: 'auto' }} />
          </div>
          <div className="cmp-meta">
            {hasBarcode ? format + ' barcode' : 'Enter a value to preview'}
          </div>
        </div>
      </div>

      <div className="cmp-actions">
        <button className="btn btn-secondary" onClick={copySvg} disabled={!hasBarcode}>
          <window.Icon name="clipboard" size={16} /> {copied ? 'Copied!' : 'Copy SVG'}
        </button>
        <button className="btn btn-secondary" onClick={downloadSvg} disabled={!hasBarcode}>
          <window.Icon name="download" size={16} /> Download SVG
        </button>
        <button className="btn btn-primary" onClick={downloadPng} disabled={!hasBarcode}>
          <window.Icon name="download" size={16} /> Download PNG
        </button>
      </div>
    </div>
  );
};
