// Stopwatch → scenario mapping (KAR-843): suggest which measured station a
// G60 process row belongs to, by significant-token overlap of the free-text
// names ("IM 2700t Spritzguss" ↔ "Spritzguss IM2700t"). Pure + unit-tested;
// the user corrects suggestions via dropdown (same pattern as manual step
// matching, KAR-845).

export interface StationMeasurement {
  stationName: string
  medianSec: number
  measurementCount: number
}

/** Tokens of length ≥ 3 (or containing a digit), lowercased, alnum only. */
function tokens(s: string): Set<string> {
  return new Set(
    s
      .toLowerCase()
      .split(/[^0-9a-zäöüß]+/)
      .filter((t) => t.length >= 3 || /\d/.test(t)),
  )
}

/** A token is STRONG when it is specific: carries a digit or is ≥ 6 chars —
 * a single generic shop-floor word ("Linie") must not produce a match. */
function isStrong(t: string): boolean {
  return /\d/.test(t) || t.length >= 6
}

interface Overlap {
  shared: number
  strong: number
}

function score(rowLabel: string, stationName: string): Overlap {
  const a = tokens(rowLabel)
  const b = tokens(stationName)
  const out: Overlap = { shared: 0, strong: 0 }
  if (a.size === 0 || b.size === 0) return out
  for (const t of a) {
    if (b.has(t)) {
      out.shared += 1
      if (isStrong(t)) out.strong += 1
      continue
    }
    // "im2700t" vs "2700t": digit-bearing tokens match on containment.
    if (/\d/.test(t)) {
      for (const u of b) {
        if (t.includes(u) || u.includes(t)) {
          out.shared += 1
          out.strong += 1
          break
        }
      }
    }
  }
  return out
}

/**
 * Best station for a process-row label; null when nothing plausibly matches.
 * Confidence rule: at least two shared tokens, or one STRONG shared token.
 * Deterministic: stations are scanned in the given (name-sorted) order.
 */
export function suggestStationForRow(
  rowLabel: string,
  stations: StationMeasurement[],
): StationMeasurement | null {
  let best: StationMeasurement | null = null
  let bestKey = 0
  for (const st of stations) {
    const sc = score(rowLabel, st.stationName)
    const confident = sc.shared >= 2 || sc.strong >= 1
    if (!confident) continue
    const key = sc.shared * 10 + sc.strong
    if (key > bestKey) {
      bestKey = key
      best = st
    }
  }
  return best
}
