/**
 * SVG Theme Post-Processor
 *
 * Transforms KiCad CLI SVG export into the Adom branded dark theme.
 * Replaces default KiCad colors with the Adom design system palette.
 *
 * KiCad default SVG uses:
 *   - White/transparent background
 *   - #840000 (dark red) strokes for body, group labels
 *   - #840000 text for pin names, numbers
 *   - Standard line widths
 *
 * Adom theme uses:
 *   - Dark canvas background (#0d1117)
 *   - Body: dark gradient fill, #30363d border, rounded corners
 *   - Pin wires: #4a5568 resting → #00e6dc hover
 *   - Pin names: #e6edf3 → #00e6dc hover
 *   - Pin numbers: #8b949e (discrete only; stripped from IC SVGs)
 *   - Group labels: #E6B450 (warm amber — visible on dark body)
 */

// KiCad SVG colors we want to replace
const KICAD_BODY_STROKE = '#840000';   // Body outlines, pin wires, geometric shapes
const KICAD_BODY_FILL = '#ffffc2';     // KiCad background fill for body
const KICAD_TEXT_STROKE = '#A90000';   // Stroked-text paths (pin names, numbers, group labels)
const KICAD_HIDDEN_TEXT = '#006464';   // Hidden property text (Reference, Footprint, etc.)

// Adom theme target colors
export const THEME_COLORS = {
  canvasBg: '#0d1117',
  bodyStroke: '#30363d',
  bodyFill: '#1a2332',
  bodyFillGrad: '#141c27',
  pinWire: '#4a5568',
  pinWireHover: '#00e6dc',
  pinName: '#ffffff',
  pinNameHover: '#00e6dc',
  pinNumber: '#8b949e',
  groupLabel: '#E6B450',
  groupLabelHover: '#FFD180',
  refText: '#484f58',
  valueText: '#8b949e',
  pinDot: '#4a5568',
  pinDotHover: '#00e6dc',
};

/**
 * Apply Adom dark theme to a KiCad-exported SVG string.
 *
 * Strategy: Inject a <style> block into the SVG that overrides KiCad's
 * inline styles with Adom theme colors. Also inject CSS classes for
 * hover effects that the viewer JS will trigger.
 *
 * @param {string} svg - Raw SVG string from KiCad CLI export
 * @returns {string} Themed SVG string
 */
export function applyDarkTheme(svg) {
  // Strip XML declaration and DOCTYPE
  let themed = svg
    .replace(/<\?xml[^?]*\?>/, '')
    .replace(/<!DOCTYPE[^>]*>/, '')
    .trim();

  // Replace KiCad's default background rect (if present)
  themed = themed.replace(
    /(<rect[^>]*fill=")white("[^>]*>)/,
    `$1${THEME_COLORS.canvasBg}$2`
  );

  // Inject a <defs> section with gradient for body rectangles
  const defs = `
<defs>
  <linearGradient id="adom-body-grad" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0%" stop-color="${THEME_COLORS.bodyFill}"/>
    <stop offset="100%" stop-color="${THEME_COLORS.bodyFillGrad}"/>
  </linearGradient>
</defs>`;

  // Inject <style> block for interactive hover effects (JS-toggled classes)
  const style = `
<style>
  /* Stroked text groups (KiCad renders text as paths in <g class="stroked-text">) */
  g.stroked-text path {
    stroke: ${THEME_COLORS.pinName} !important;
    fill: ${THEME_COLORS.pinName} !important;
  }

  /* Hidden text elements (used for hit detection) */
  text[opacity="0"] {
    fill: ${THEME_COLORS.pinName} !important;
  }

  /* Pin highlight state (toggled by JS) */
  .pin-highlight path {
    stroke: ${THEME_COLORS.pinWireHover} !important;
  }
  .pin-highlight g.stroked-text path {
    stroke: ${THEME_COLORS.pinNameHover} !important;
  }

  /* Group label highlight */
  .group-highlight g.stroked-text path {
    stroke: ${THEME_COLORS.groupLabelHover} !important;
  }
</style>`;

  // Insert defs and style right after the opening <svg> tag
  themed = themed.replace(
    /(<svg[^>]*>)/,
    `$1\n${defs}\n${style}`
  );

  // ── Direct color replacement ──────────────────────────────────────
  // KiCad CLI outputs colors in TWO forms:
  //   1. Inline style: style="stroke:#840000; ..."
  //   2. Attributes: stroke="#840000" fill="#ffffc2"
  // We must handle both.

  // Replace #840000 strokes (body, pins, wires) → theme pin wire color
  // In style="..." attributes:
  themed = themed.replace(/stroke:#840000/g, `stroke:${THEME_COLORS.pinWire}`);
  // In stroke="..." attributes:
  themed = themed.replace(/stroke="#840000"/g, `stroke="${THEME_COLORS.pinWire}"`);

  // Replace #840000 fills (filled shapes like arrow triangles, dots)
  // In style="..." attributes:
  themed = themed.replace(/fill:#840000/g, `fill:${THEME_COLORS.pinDot}`);
  // In fill="..." attributes:
  themed = themed.replace(/fill="#840000"/g, `fill="${THEME_COLORS.pinDot}"`);

  // Replace body fill #ffffc2 → gradient
  themed = themed.replace(/fill:#ffffc2/gi, `fill:url(#adom-body-grad)`);
  themed = themed.replace(/fill="#ffffc2"/gi, `fill="url(#adom-body-grad)"`);
  themed = themed.replace(/fill="rgb\(255,\s*255,\s*194\)"/gi, `fill="url(#adom-body-grad)"`);

  // Replace #000000 fills on the root <g> (KiCad's default group fill)
  // This would make everything black on dark bg — make it transparent
  themed = themed.replace(
    /(<g\s+style="fill:#000000[^"]*")/,
    (match) => match.replace('fill:#000000', 'fill:none')
  );

  // Replace #A90000 strokes (KiCad's stroked-text paths — pin names, numbers, group labels)
  // These are rendered as thin stroke paths inside <g class="stroked-text"> elements
  themed = themed.replace(/stroke:#A90000/g, `stroke:${THEME_COLORS.pinName}`);
  themed = themed.replace(/stroke="#A90000"/g, `stroke="${THEME_COLORS.pinName}"`);
  themed = themed.replace(/fill:#A90000/g, `fill:${THEME_COLORS.pinName}`);
  themed = themed.replace(/fill="#A90000"/g, `fill="${THEME_COLORS.pinName}"`);

  // Replace #006464 (KiCad's hidden text teal) with theme color
  themed = themed.replace(/stroke:#006464/g, `stroke:${THEME_COLORS.refText}`);
  themed = themed.replace(/fill:#006464/g, `fill:${THEME_COLORS.refText}`);

  return themed;
}

/**
 * Identify group label text elements in the SVG and re-color them.
 * KiCad renders group labels as stroked-text groups with font-size ~1.016.
 * We need to make them purple instead of the default pin color.
 *
 * @param {string} svg - SVG string (after applyDarkTheme)
 * @param {string[]} groupNames - Array of group label text strings
 * @returns {string} SVG with group labels colored
 */
export function colorGroupLabels(svg, groupNames) {
  if (!groupNames || groupNames.length === 0) return svg;

  // Group labels in KiCad SVG appear as:
  // <text ...opacity="0"...>GROUP NAME</text>
  // followed by <g class="stroked-text"><desc>GROUP NAME</desc>...paths...</g>
  //
  // We add a CSS class to the stroked-text group so we can color it purple
  for (const name of groupNames) {
    const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    // Find the stroked-text group with this label
    const re = new RegExp(
      `(<g class="stroked-text"><desc>${escaped}</desc>)`,
      'g'
    );
    svg = svg.replace(re, `<g class="stroked-text group-label-text"><desc>${name}</desc>`);
  }

  // Add CSS rule for group labels
  svg = svg.replace(
    '</style>',
    `  g.group-label-text path {
    stroke: ${THEME_COLORS.groupLabel} !important;
    fill: ${THEME_COLORS.groupLabel} !important;
  }
  g.group-label-text.group-highlight path {
    stroke: ${THEME_COLORS.groupLabelHover} !important;
  }
</style>`
  );

  return svg;
}

/**
 * Strip Reference and Value property text from the SVG.
 * KiCad CLI places these at arbitrary positions that overlap the body.
 * The viewer toolbar and info bar already show this metadata.
 *
 * @param {string} svg - SVG string
 * @param {string} reference - Reference designator (e.g., "U", "D", "Q")
 * @param {string} value - Value text (part name)
 * @returns {string} SVG with ref/value text removed
 */
export function stripRefValueText(svg, reference, value) {
  for (const propText of [reference + '?', reference, value]) {
    if (!propText) continue;
    const esc = propText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    // Strip invisible <text> element (may have nested <g> wrapper before the stroked-text)
    svg = svg.replace(
      new RegExp('<text[^>]*opacity="0"[^>]*>' + esc + '</text>', 'g'),
      ''
    );
    // Strip the stroked-text group (the visible rendered text)
    svg = svg.replace(
      new RegExp('<g class="stroked-text"><desc>' + esc + '</desc>[\\s\\S]*?</g>', 'g'),
      ''
    );
  }
  return svg;
}

/**
 * Color pin number text in an IC symbol SVG to distinguish from pin names.
 *
 * KiCad renders pin names (inside body) and pin numbers (on wires) with the
 * same color. This adds a CSS class to pin number stroked-text groups so they
 * render in muted gray — visually subordinate to the white pin names.
 *
 * @param {string} svg - SVG string (after applyDarkTheme)
 * @param {string[]} pinNumbers - Array of pin number strings
 * @param {string[]} pinNames - Array of pin name strings (to avoid re-coloring names)
 * @param {string[]} groupNames - Array of group label strings (to avoid re-coloring those)
 * @returns {string} SVG with pin numbers colored distinctly
 */
export function colorPinNumbers(svg, pinNumbers, pinNames = [], groupNames = []) {
  if (!pinNumbers || pinNumbers.length === 0) return svg;

  // Build a set of labels we must NOT re-color (pin names + group labels)
  const protect = new Set([...pinNames, ...groupNames]);

  for (const num of pinNumbers) {
    if (protect.has(num)) continue;
    const esc = num.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    // Add pin-number-text class to the stroked-text group
    svg = svg.replace(
      new RegExp(`(<g class="stroked-text"><desc>${esc}</desc>)`, 'g'),
      `<g class="stroked-text pin-number-text"><desc>${num}</desc>`
    );
  }

  // Add CSS rule for pin numbers (muted gray, smaller visual weight)
  svg = svg.replace(
    '</style>',
    `  g.pin-number-text path {
    stroke: ${THEME_COLORS.pinNumber} !important;
    fill: ${THEME_COLORS.pinNumber} !important;
  }
</style>`
  );

  return svg;
}