/**
 * Price field cleaning and formatting utilities
 */

/**
 * Normalizes a numeric string that may use US or European formatting conventions.
 *
 * Handles the ambiguity between comma-as-thousands (US: "1,234.56") and
 * comma-as-decimal (European: "1.234,56" or "1,50") using these heuristics:
 *
 * 1. Both comma AND period present → last one is the decimal separator
 *    - "1,234.56" → period last → US → "1234.56"
 *    - "1.234,56" → comma last → EU → "1234.56"
 *
 * 2. Only comma, no period → check digit count after last comma:
 *    - 1-2 digits → decimal comma: "1,50" → "1.50"
 *    - 3 digits   → thousands:    "1,500" → "1500"
 *
 * 3. Only period or neither → return as-is
 */
function normalizeNumericSeparators(value: string): string {
  if (value.includes(".") && value.includes(",")) {
    const lastComma = value.lastIndexOf(",");
    const lastPeriod = value.lastIndexOf(".");
    if (lastPeriod > lastComma) {
      // US: "1,234.56" → remove commas
      return value.replace(/,/g, "");
    } else {
      // European: "1.234,56" → remove periods, comma→period
      return value.replace(/\./g, "").replace(",", ".");
    }
  }

  if (value.includes(",")) {
    const match = value.match(/,(\d+)$/);
    if (match && match[1].length <= 2) {
      // Decimal comma: "1,50" → "1.50", "1,5" → "1.5"
      return value.replace(",", ".");
    }
    // Thousands comma(s): "1,500" or "1,000,000" → remove all
    return value.replace(/,/g, "");
  }

  return value;
}

/**
 * Strips currency formatting from a price string without rounding.
 *
 * Removes currency symbols and whitespace, normalizes European decimal commas,
 * and returns the raw numeric string. Full precision is preserved.
 *
 * @returns Stripped numeric string, or original value if not a valid number
 *
 * @example
 * stripPriceFormatting(" $           1.50") // "1.50"
 * stripPriceFormatting("$1,234.56")         // "1234.56"
 * stripPriceFormatting("1.234,56")          // "1234.56"
 * stripPriceFormatting("1,50")              // "1.50"
 * stripPriceFormatting("3.625")             // "3.625"
 * stripPriceFormatting("invalid")           // "invalid"
 */
export function stripPriceFormatting(value: string): string {
  // Step 1: Strip whitespace and currency symbols (keep commas/periods for separator detection)
  let cleaned = value.replace(/[\s$€£¥]/g, "");

  // Step 2: Normalize decimal/thousands separators
  cleaned = normalizeNumericSeparators(cleaned);

  // Verify it's actually a number after normalization
  const numValue = parseFloat(cleaned);
  if (!isNaN(numValue) && cleaned !== "") {
    return cleaned;
  }
  return value;
}

/**
 * Cleans a price field by removing currency symbols and formatting to 2 decimal places
 *
 * - Removes currency symbols and whitespace
 * - Normalizes European decimal commas
 * - Converts to number and formats with 2 decimal places
 * - Returns original value if conversion fails
 *
 * @param value - Price value to clean (string or number)
 * @returns Cleaned price string formatted to 2 decimals, or original value if invalid
 *
 * @example
 * cleanPriceField("$1,234.56") // "1234.56"
 * cleanPriceField(" $  99.9")  // "99.90"
 * cleanPriceField("1,50")      // "1.50"
 * cleanPriceField(123.456)     // "123.46"
 * cleanPriceField("invalid")   // "invalid"
 */
export function cleanPriceField(value: string | number): string {
  if (typeof value === "string") {
    const cleaned = stripPriceFormatting(value);
    const numValue = parseFloat(cleaned);
    if (!isNaN(numValue)) {
      return numValue.toFixed(2);
    }
    return value;
  }

  if (typeof value === "number") {
    return value.toFixed(2);
  }

  return String(value);
}

/**
 * Cleans multiple price fields in a data object
 *
 * @param data - Object containing price fields
 * @param priceFields - Array of field keys to clean
 * @returns New object with cleaned price fields
 *
 * @example
 * cleanPriceFields({ msrp: "$99.99", cost_each: "$50.00" }, ["msrp", "cost_each"])
 * // { msrp: "99.99", cost_each: "50.00" }
 */
export function cleanPriceFields<T extends Record<string, any>>(
  data: T,
  priceFields: (keyof T)[]
): T {
  const cleaned = { ...data };

  for (const field of priceFields) {
    if (cleaned[field] !== undefined && cleaned[field] !== null) {
      cleaned[field] = cleanPriceField(cleaned[field]) as any;
    }
  }

  return cleaned;
}
