// Verlagerte Untervorgänge (Spezifikation Kap. 7.4, R-10).
//
// Untervorgänge sind die beschreibende Ebene des Fertigungsblatts: „Bauteil auf
// Vorrichtung legen", „zwei Schrauben anziehen". Sie tragen keine eigene Zeit
// und keine eigenen Kosten — deshalb übersieht man leicht, dass ihr
// Verschwinden eine Frage aufwirft.
//
// Fallen Arbeitsschritte weg, während die Taktzeiten der Hauptlinie
// unverändert bleiben, ist das ein Verhandlungspunkt: Entweder waren die
// Schritte nie zeitrelevant, oder die Zeit steckt noch im Preis. Beides ist
// möglich, aber nur eines ist richtig — und wer die Frage nicht stellt, bekommt
// keine Antwort.
//
// Pure Funktionen, keine I/O.

import { normalizeMaterialName } from './material-name'

export interface SubOperation {
  row: number
  name: string
}

export interface SubOperationDiff {
  removed: SubOperation[]
  added: SubOperation[]
  /** Gleiche Stelle in der Reihenfolge, anderer Name. */
  renamed: Array<{ award: SubOperation; current: SubOperation }>
  counts: { award: number; current: number; removed: number; added: number; renamed: number }
}

/**
 * Untervorgänge beider Stände vergleichen.
 *
 * Zugeordnet wird über den Namen, mehrfach vorkommende über die erhaltene
 * Reihenfolge — dieselbe Logik wie bei den Gleichteilen der Stückliste, und aus
 * demselben Grund: „Zwei Schrauben anziehen" steht an vielen Stellen, und nur
 * die Reihenfolge sagt, welches welches ist.
 *
 * Was danach übrig bleibt und sich paaren lässt, gilt als Umbenennung: gleiche
 * Stelle in der verbliebenen Reihenfolge, anderer Wortlaut.
 */
export function diffSubOperations(award: SubOperation[], current: SubOperation[]): SubOperationDiff {
  const key = (s: SubOperation) => normalizeMaterialName(s.name).normalized

  const pool = new Map<string, SubOperation[]>()
  for (const c of [...current].sort((a, b) => a.row - b.row)) {
    const k = key(c)
    if (k === '') continue
    pool.set(k, [...(pool.get(k) ?? []), c])
  }

  const removed: SubOperation[] = []
  const matchedCurrent = new Set<number>()

  for (const a of [...award].sort((x, y) => x.row - y.row)) {
    const k = key(a)
    // Eine namenlose Zeile ist kein Arbeitsschritt, sondern Rauschen — sie als
    // Wegfall zu zählen würde die Zeitgutschrift-Frage grundlos aufwerfen.
    if (k === '') continue
    const hits = pool.get(k)
    if (!hits || hits.length === 0) {
      removed.push(a)
      continue
    }
    const partner = hits.shift()!
    matchedCurrent.add(partner.row)
  }

  const added = [...current]
    .sort((a, b) => a.row - b.row)
    .filter((c) => !matchedCurrent.has(c.row) && key(c) !== '')

  // Umbenennungen aus dem Rest: paarweise in der verbliebenen Reihenfolge.
  // Bewusst konservativ — nur solange auf beiden Seiten etwas übrig ist, und
  // ohne Anspruch, die inhaltlich „richtige" Paarung zu treffen. Es geht darum,
  // eine reine Umbenennung nicht als Wegfall plus Zuwachs zu zählen.
  const renamed: SubOperationDiff['renamed'] = []
  while (removed.length > 0 && added.length > 0) {
    renamed.push({ award: removed.shift()!, current: added.shift()! })
  }

  return {
    removed,
    added,
    renamed,
    counts: {
      award: award.length,
      current: current.length,
      removed: removed.length,
      added: added.length,
      renamed: renamed.length,
    },
  }
}

export interface TimeCreditQuestion {
  /** Sind Arbeitsschritte weggefallen, ohne dass sich Taktzeiten geändert haben? */
  raised: boolean
  removedCount: number
  questionDe: string | null
}

/**
 * Die Zeitgutschrift-Frage stellen — oder eben nicht.
 *
 * Sie ist nur dann begründet, wenn beides zutrifft: Arbeitsschritte sind
 * weggefallen UND die zugeordneten Stationen sind parameteridentisch. Fehlt
 * eines von beidem, gibt es nichts zu fragen: Ohne Wegfall ist nichts
 * verschwunden, und bei geänderten Taktzeiten ist die Zeit ja sichtbar
 * verrechnet.
 */
export function timeCreditQuestion(diff: SubOperationDiff, mainLineUnchanged: boolean): TimeCreditQuestion {
  const raised = diff.removed.length > 0 && mainLineUnchanged
  return {
    raised,
    removedCount: diff.removed.length,
    questionDe: raised
      ? `${diff.removed.length} Arbeitsschritte sind entfallen, während die Taktzeiten der zugeordneten Stationen unverändert blieben. Wo ist die Zeit verrechnet?`
      : null,
  }
}
