// src/utils/svgColor.ts
// (keep your existing helpers) add these:

// Parse #hex, rgb(), or rgba() into RGBA [0..255], returns null if unsupported
function parseColor(input: string): { r: number; g: number; b: number; a: number } | null {
  if (!input) return null;
  const s = input.trim().toLowerCase();

  // #rgb, #rgba, #rrggbb, #rrggbbaa
  if (s.startsWith("#")) {
    const h = s.slice(1);
    if (h.length === 3 || h.length === 4) {
      const r = parseInt(h[0] + h[0], 16);
      const g = parseInt(h[1] + h[1], 16);
      const b = parseInt(h[2] + h[2], 16);
      const a = h.length === 4 ? parseInt(h[3] + h[3], 16) : 255;
      return { r, g, b, a };
    }
    if (h.length === 6 || h.length === 8) {
      const r = parseInt(h.slice(0, 2), 16);
      const g = parseInt(h.slice(2, 4), 16);
      const b = parseInt(h.slice(4, 6), 16);
      const a = h.length === 8 ? parseInt(h.slice(6, 8), 16) : 255;
      return { r, g, b, a };
    }
    return null;
  }

  // rgb / rgba
  const rgb = s.match(/^rgba?\(\s*([0-9.]+)\s*,\s*([0-9.]+)\s*,\s*([0-9.]+)(?:\s*,\s*([0-9.]+))?\s*\)$/i);
  if (rgb) {
    const r = Math.round(parseFloat(rgb[1]));
    const g = Math.round(parseFloat(rgb[2]));
    const b = Math.round(parseFloat(rgb[3]));
    const a = rgb[4] != null ? Math.round(parseFloat(rgb[4]) * 255) : 255;
    return { r, g, b, a };
  }

  return null; // named colors etc. (can extend later)
}

// WCAG relative luminance 0..1
function relativeLuminance(r: number, g: number, b: number): number {
  const toLin = (c: number) => {
    const v = c / 255;
    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
  };
  const R = toLin(r), G = toLin(g), B = toLin(b);
  return 0.2126 * R + 0.7152 * G + 0.0722 * B;
}

// Convert hex like #112233 or #112233ff
function toHex(r: number, g: number, b: number, a = 255): string {
  const h = (n: number) => n.toString(16).padStart(2, "0");
  return a === 255 ? `#${h(r)}${h(g)}${h(b)}` : `#${h(r)}${h(g)}${h(b)}${h(a)}`;
}

const COLOR_ATTRS = /(fill|stroke|stop-color|flood-color|lighting-color)\s*=\s*("([^"]+)"|'([^']+)')/gi;
const CSS_HEX = /(#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8}))\b/gi;
const CSS_RGB = /(rgba?\(\s*[0-9.\s,]+\))/gi;

/**
 * Duotone: map all colors by luminance threshold to two target hex colors.
 * - Everything with luminance <= threshold -> darkColor
 * - Everything with luminance >  threshold -> lightColor
 * Supports hex/rgb/rgba in attributes and simple <style> blocks.
 */
export function recolorSvgDuotone(
  svg: string,
  options: {
    darkColor: string;           // hex like "#111827"
    lightColor: string;          // hex like "#f8fafc"
    threshold?: number;          // 0..1 (default 0.5)
    affectStrokes?: boolean;     // default true
    includeGradients?: boolean;  // default true
  }
): string {
  const threshold = options.threshold ?? 0.5;
  const affectStrokes = options.affectStrokes ?? true;
  const includeGradients = options.includeGradients ?? true;

  const darkHex = normalizeHex(options.darkColor);
  const lightHex = normalizeHex(options.lightColor);

  // 1) Replace in attributes (fill, stroke, stop-color, etc.)
  let out = svg.replace(COLOR_ATTRS, (m, attr, whole, dq, sq) => {
    const val = (dq || sq || "").trim();
    const c = parseColor(val);
    if (!c) return m;
    const lum = relativeLuminance(c.r, c.g, c.b);
    const tgt = lum <= threshold ? darkHex : lightHex;

    const attrName = String(attr).toLowerCase();
    if (!affectStrokes && attrName === "stroke") return m;
    if (!includeGradients && attrName === "stop-color") return m;

    const pre = m.slice(0, m.indexOf(val));
    const post = m.slice(m.indexOf(val) + val.length);
    return `${pre}${tgt}${post}`;
  });

  // 2) Replace in style blocks (hex + rgb/rgba)
  out = out.replace(CSS_HEX, (_m, hex) => {
    const c = parseColor(hex);
    if (!c) return hex;
    const lum = relativeLuminance(c.r, c.g, c.b);
    const tgt = lum <= threshold ? darkHex : lightHex;
    return tgt;
  });

  out = out.replace(CSS_RGB, (_m, rgbLike) => {
    const c = parseColor(rgbLike);
    if (!c) return rgbLike;
    const lum = relativeLuminance(c.r, c.g, c.b);
    const tgt = lum <= threshold ? darkHex : lightHex;
    return tgt;
  });

  // 3) Add default fill for unfilled shapes (optional, keeps shapes visible)
  out = out.replace(
    /<((path|rect|circle|ellipse|polygon|polyline|line)\b)((?:(?!>)[\s\S])*)>/gi,
    (m: string, tagOpen: string, _tag: string, attrs: string) => {
      if (/ fill\s*=/.test(attrs)) return m; // explicit fill
      if (/ stroke\s*=/i.test(attrs) && !affectStrokes) return m;
      // Default unfilled shapes to dark color (or to light? choose dark for contrast)
      return `<${tagOpen}${attrs} fill="${darkHex}">`;
    }
  );

  return out;
}
