/**
 * Shared exercise search utilities — fuzzy matching + abbreviation expansion.
 * Used by both ExercisePicker (log workout) and ExercisesClient (exercise library).
 */

// Common gym abbreviations
const ABBREVIATIONS: Record<string, string> = {
  kb: "kettlebell",
  db: "dumbbell",
  bb: "barbell",
  ghd: "glute ham developer",
  rdl: "romanian deadlift",
  ohp: "overhead press",
};

/**
 * Expand a search query into multiple variants using known abbreviations.
 * e.g. "kb swing" → ["kb swing", "kettlebell swing"]
 */
export function expandAbbreviations(query: string): string[] {
  const lower = query.toLowerCase().trim();
  const variants: string[] = [lower];

  // Check if the whole query is an abbreviation
  if (ABBREVIATIONS[lower]) {
    variants.push(ABBREVIATIONS[lower]);
  }

  // Check if the query starts with an abbreviation followed by a space
  for (const [abbr, full] of Object.entries(ABBREVIATIONS)) {
    if (lower.startsWith(abbr + " ")) {
      variants.push(full + lower.slice(abbr.length));
    }
  }

  return variants;
}

/**
 * Score how well a query matches a target string.
 * Lower = better match. Returns -1 for no match.
 *
 * Priority: exact match (0) > starts with (1) > word starts with (2) > substring (3) > fuzzy chars (4+)
 */
export function fuzzyScore(query: string, target: string): number {
  const q = query.toLowerCase();
  const t = target.toLowerCase();

  if (t === q) return 0;
  if (t.startsWith(q)) return 1;

  const words = t.split(/\s+/);
  if (words.some((w) => w.startsWith(q))) return 2;
  if (t.includes(q)) return 3;

  // Fuzzy character match
  let qi = 0;
  for (let ti = 0; ti < t.length && qi < q.length; ti++) {
    if (t[ti] === q[qi]) qi++;
  }

  return qi === q.length ? 4 + (t.length - q.length) : -1;
}

/**
 * Search exercises using fuzzy matching + abbreviation expansion.
 * Returns scored exercises sorted by best match, or -1 for no match.
 */
export function scoreExercise(query: string, exerciseName: string): number {
  const variants = expandAbbreviations(query);
  const scores = variants
    .map((q) => fuzzyScore(q, exerciseName))
    .filter((s) => s >= 0);

  return scores.length > 0 ? Math.min(...scores) : -1;
}
