// Loop 4 (Roadmap): abgeleitete Vergleichbarkeits-Ampel für den V2-Kopf.
//
// Exit-Kriterium „kein produktiver Vergleich bleibt ohne begründeten
// Vergleichstyp / unbestimmte Einordnung hat einen sichtbaren Reviewstatus".
// Die Ampel ist eine PRÜF-Aussage, keine Deklaration: Sie fasst zusammen, was
// die deterministischen Identitäts-Checks des Laufs (plausibility.ts —
// part_number_mismatch seit KAR-799, D16-Detektoren seit 08.08.2026) als
// persistierte Befunde hinterlassen haben. Das System rät nichts — es liest
// die eigenen Befunde. Jede Einstufung trägt ihre Begründung (reasonsDe),
// damit die Ampel nie stärker behauptet als ihre Grundlage.
//
// Regeln (konservativ, PO-Linie „weiche Befunde"):
// - part_number_mismatch → not_comparable (der Check selbst sagt „dürfen
//   nicht verglichen werden" — kritischste Identitätsverletzung).
// - Lieferanten-/Varianten-Identität verletzt (supplier_mismatch,
//   supplier_no_mismatch, variant_changed) → limited: vergleichbar, aber die
//   Lesart der Deltas ändert sich (anderer Lieferant/andere Variante).
// - Sonst → comparable, begründet mit „keine Identitäts-Befunde" — bewusst
//   NICHT „geprüft und fehlerfrei in jeder Hinsicht".
// - Anfrageversion/Änderungsindex/Datum/Dateiname bleiben Hinweise ohne
//   Ampel-Wirkung (zwischen Ständen legitim beweglich, siehe plausibility.ts).
//
// Pure. Kein DB-/Framework-Zugriff (check:qaf-core-portability).

/** Kap.-21-Ampelwerte — seit Loop 4 hier als framework-freie Quelle; die
 * Header-Komponente (qaf-v2-header.tsx) aliasiert ihren Typ hierauf (dasselbe
 * Muster wie DeclaredComparisonType/R-03). */
export type ComparabilityStatus = 'comparable' | 'limited' | 'not_comparable' | 'undetermined'

/** Struktur-Subset der persistierten Issue-Zeile (kein DB-Import — dasselbe
 * Muster wie MakeOrBuyShareInput in plausibility.ts). */
export interface ComparabilityIssueInput {
  issue_type: string
}

export interface DerivedComparability {
  status: ComparabilityStatus
  /** Begründungen für den Kopf (Tooltip der Ampel) — nie leer. */
  reasonsDe: string[]
}

const NOT_COMPARABLE_TYPES = new Set(['part_number_mismatch'])
const LIMITED_TYPES = new Set(['supplier_mismatch', 'supplier_no_mismatch', 'variant_changed'])

const LIMITED_LABEL_DE: Record<string, string> = {
  supplier_mismatch: 'Lieferant weicht zwischen den Ständen ab',
  supplier_no_mismatch: 'Lieferantennummer weicht zwischen den Ständen ab',
  variant_changed: 'Variante weicht zwischen den Ständen ab',
}

export interface DeriveComparabilityOptions {
  /**
   * false, wenn der Lauf VOR den erweiterten Identitätsprüfungen (D16,
   * engineConfig ≥ 1.5.0) stattfand: „keine Befunde" heißt dann nur „die
   * Kern-Checks (Sachnummer/Variante, seit KAR-799) fanden nichts" — die
   * Lieferanten-Prüfung lief nie. Die Ampel bleibt comparable, aber die
   * Begründung benennt die Grenze, statt einen vollen Clean-Run zu
   * behaupten (Review-Befund 10.08.). Default true (frische Läufe).
   */
  identityChecksComplete?: boolean
}

/** Leitet die Kopf-Ampel aus den persistierten Identitäts-Befunden ab. */
export function deriveComparability(
  issues: readonly ComparabilityIssueInput[],
  options: DeriveComparabilityOptions = {},
): DerivedComparability {
  if (issues.some((i) => NOT_COMPARABLE_TYPES.has(i.issue_type))) {
    return {
      status: 'not_comparable',
      reasonsDe: ['Sachnummern unterschiedlich — die Stände gehören nicht zum selben Teil.'],
    }
  }
  const limited = [...new Set(issues.filter((i) => LIMITED_TYPES.has(i.issue_type)).map((i) => i.issue_type))]
  if (limited.length > 0) {
    return {
      status: 'limited',
      reasonsDe: limited.map((t) => LIMITED_LABEL_DE[t] ?? t),
    }
  }
  if (options.identityChecksComplete === false) {
    return {
      status: 'comparable',
      reasonsDe: [
        'Keine Identitäts-Befunde — der Lauf lief allerdings vor den erweiterten Identitätsprüfungen (Lieferant/Lieferantennummer wurden damals nicht geprüft); ein erneuter Vergleichslauf prüft vollständig.',
      ],
    }
  }
  return {
    status: 'comparable',
    reasonsDe: ['Keine Identitäts-Befunde aus dem Vergleichslauf.'],
  }
}
