// Tests for multi-qaf/variant-matcher.ts (KAR-936 / Multi-QAF-Programm P2.2).
//
// Covers every Master-Prompt §9 tolerance scenario synthetically: reorder,
// rename, extra/missing dimension, DE/EN dimension values, typo tolerance,
// split, merge, duplicate-looking variants, a genuine score tie, the
// structural-anchor tiebreak, and the manual-override review workflow
// (winning + identity-drift drop). Real-file scenarios (self-match + the
// container-assembly.ts cross-sheet fallback) live in
// variant-matcher.real-files.test.ts (env-gated).

import { describe, expect, it } from 'vitest'
import {
  DEFAULT_VARIANT_MATCH_CONFIG,
  matchVariants,
  matchVariantsWithOverrides,
  identitySnapshotsEqual,
  identitySnapshotFor,
  findAllByIdentitySnapshot,
  replaceOverrideForVariant,
  removeActiveOverridesForVariant,
  type VariantMatchOverride,
  type VariantMatchResult,
} from '../variant-matcher'
import { buildCompositeCanonicalKey, makeDimensionValue } from '../identity'
import type { VariantDefinition, VariantDimensions } from '../types'

function dims(entries: Record<string, string>): VariantDimensions {
  const out: Record<string, ReturnType<typeof makeDimensionValue>> = {}
  for (const [k, v] of Object.entries(entries)) out[k] = makeDimensionValue(v)
  return out
}

function variant(id: string, dimEntries: Record<string, string>, extra: Partial<VariantDefinition> = {}): VariantDefinition {
  const dimensions = dims(dimEntries)
  return {
    stableInternalId: id,
    originalColumn: 'Q',
    originalColumnIndex: 17,
    originalVariantNumber: null,
    originalLabels: [],
    normalizedLabels: [],
    compositeCanonicalKey: buildCompositeCanonicalKey(dimensions, id),
    dimensions,
    annualVolume: null,
    peakVolume: null,
    lifetimeVolume: null,
    currency: null,
    activeState: 'active',
    sourceReferences: [],
    confidence: 1,
    ...extra,
  }
}

function matchedOf(results: readonly VariantMatchResult[]) {
  return results.filter((r): r is Extract<VariantMatchResult, { kind: 'matched' }> => r.kind === 'matched')
}

describe('matchVariants — stage 1 (raw_exact)', () => {
  it('matches identical dimensions regardless of column (reorder tolerance)', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU' }, { originalColumn: 'Q' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU' }, { originalColumn: 'AF' })]
    const results = matchVariants(left, right)
    expect(results).toHaveLength(1)
    expect(results[0]).toMatchObject({ kind: 'matched', stage: 'raw_exact', confidence: 1, leftId: 'L1', rightId: 'R1' })
  })

  it('is rename-tolerant: label text is irrelevant to identity, only dimension values are compared', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD' }, { originalLabels: ['Variante Alpha'] })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD' }, { originalLabels: ['Variante Beta (renamed)'] })]
    const results = matchVariants(left, right)
    expect(matchedOf(results)).toHaveLength(1)
    expect(matchedOf(results)[0]!.stage).toBe('raw_exact')
  })

  it('never treats two empty-key variants as an identity match', () => {
    const left = [variant('L1', {})]
    const right = [variant('R1', {})]
    const results = matchVariants(left, right)
    expect(results.map((r) => r.kind)).toEqual(expect.arrayContaining(['unmatched_left', 'unmatched_right']))
  })
})

describe('matchVariants — stage 2 (core_subset_exact) — the KAR-935 real-file gap', () => {
  it('matches when one side has an EXTRA dimension the other side never populated (extra dim ignored)', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD', extraFromSummarySheet: 'Foo' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD', extraFromMaterialSheet: 'Bar' })]
    const results = matchVariants(left, right)
    const matched = matchedOf(results)
    expect(matched).toHaveLength(1)
    expect(matched[0]!.stage).toBe('core_subset_exact')
    expect(matched[0]!.confidence).toBeGreaterThan(0)
    expect(matched[0]!.confidence).toBeLessThan(1)
  })

  it('matches when the right side is simply missing a non-critical dimension', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD' })]
    const results = matchVariants(left, right)
    expect(matchedOf(results)[0]).toMatchObject({ stage: 'core_subset_exact' })
  })

  it('confidence scales with coverage — more shared dimensions is more certain', () => {
    const wide = matchVariants(
      [variant('L1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU' })],
      [variant('R1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU', extra: 'X' })],
    )
    const narrow = matchVariants(
      [variant('L1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU', a: '1', b: '2' })],
      [variant('R1', { vehicle: 'Q71', c: '3', d: '4' })],
    )
    expect(matchedOf(wide)[0]!.confidence).toBeGreaterThan(matchedOf(narrow)[0]!.confidence)
  })
})

describe('matchVariants — stage 3 (fuzzy_label_similarity)', () => {
  it('matches a DE/EN dimension-value synonym pair', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'Allrad' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD' })]
    const results = matchVariants(left, right)
    const matched = matchedOf(results)
    expect(matched).toHaveLength(1)
    expect(matched[0]!.stage).toBe('fuzzy_label_similarity')
    expect(matched[0]!.evidence.some((e) => e.signal === 'dimension_synonym')).toBe(true)
  })

  it('tolerates a conservative typo (small edit distance on a long-enough token)', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'Allradantrieb' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'Allradantrib' })]
    const results = matchVariants(left, right)
    const matched = matchedOf(results)
    expect(matched).toHaveLength(1)
    expect(matched[0]!.stage).toBe('fuzzy_label_similarity')
  })

  it('does NOT match when the typo is too large for the conservative similarity floor', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'ZZZ' })]
    const results = matchVariants(left, right)
    expect(matchedOf(results)).toHaveLength(0)
    expect(results.map((r) => r.kind)).toEqual(expect.arrayContaining(['unmatched_left', 'unmatched_right']))
  })
})

describe('matchVariants — split/merge suspicion', () => {
  it('flags a split: one LEFT variant with 2 independently-qualifying, non-tied RIGHT candidates', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD' })]
    const right = [
      variant('R1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU' }),
      variant('R2', { vehicle: 'Q71', driveType: 'AWD', region: 'EU', platform: 'MQB' }),
    ]
    const results = matchVariants(left, right)
    expect(results).toHaveLength(1)
    expect(results[0]).toMatchObject({ kind: 'split_suspected', leftId: 'L1', reviewRelevant: true })
    const split = results[0] as Extract<VariantMatchResult, { kind: 'split_suspected' }>
    expect([...split.rightIds].sort()).toEqual(['R1', 'R2'])
  })

  it('flags a merge: 2 LEFT variants both independently-qualifying, non-tied candidates for one RIGHT', () => {
    const left = [
      variant('L1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU' }),
      variant('L2', { vehicle: 'Q71', driveType: 'AWD', region: 'EU', platform: 'MQB' }),
    ]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD' })]
    const results = matchVariants(left, right)
    expect(results).toHaveLength(1)
    expect(results[0]).toMatchObject({ kind: 'merge_suspected', rightId: 'R1', reviewRelevant: true })
    const merge = results[0] as Extract<VariantMatchResult, { kind: 'merge_suspected' }>
    expect([...merge.leftIds].sort()).toEqual(['L1', 'L2'])
  })

  // Adversarial-review-of-#308 F3: isTopLeftForRight/isTopRightForLeft accept
  // EVERY tied-best claimant — so two DIFFERENT left variants that both
  // qualify for split_suspected can each independently top-claim the SAME
  // right variant, producing two separate, mutually contradictory
  // split_suspected results that both name that right as "their" fragment.
  // The fix clusters any provisional split/merge groups that share a top-
  // claimed secondary index into ONE ambiguous conflict instead.
  it('folds two split_suspected groups that both top-claim the SAME right variant into ONE ambiguous conflict, never two contradictory splits', () => {
    const left = [
      variant('L1', { vehicle: 'Q71', driveType: 'AWD' }),
      variant('L2', { vehicle: 'Q71', driveType: 'AWD' }),
    ]
    const right = [
      variant('Rtop', { vehicle: 'Q71', driveType: 'AWD', region: 'EU' }), // both L1, L2 tie for this one
      variant('R1weak', { vehicle: 'Q71', driveType: 'AWD', region: 'EU', platformX: 'A' }),
      variant('R2weak', { vehicle: 'Q71', driveType: 'AWD', region: 'EU', platformY: 'B' }),
    ]
    const results = matchVariants(left, right)
    expect(results.filter((r) => r.kind === 'split_suspected')).toHaveLength(0)
    expect(results).toHaveLength(1)
    expect(results[0]!.kind).toBe('ambiguous')
    const conflict = results[0] as Extract<VariantMatchResult, { kind: 'ambiguous' }>
    expect(conflict.reviewRelevant).toBe(true)
    expect([...conflict.leftIds].sort()).toEqual(['L1', 'L2'])
    expect([...conflict.rightIds].sort()).toEqual(['R1weak', 'R2weak', 'Rtop'])
  })

  it('folds two merge_suspected groups that both top-claim the SAME left variant into ONE ambiguous conflict, never two contradictory merges', () => {
    const left = [
      variant('L1weak', { vehicle: 'Q71', driveType: 'AWD', region: 'EU', platformX: 'A' }),
      variant('L2weak', { vehicle: 'Q71', driveType: 'AWD', region: 'EU', platformY: 'B' }),
      variant('Ltop', { vehicle: 'Q71', driveType: 'AWD' }), // both R1, R2 tie for this one
    ]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD' }), variant('R2', { vehicle: 'Q71', driveType: 'AWD' })]
    const results = matchVariants(left, right)
    expect(results.filter((r) => r.kind === 'merge_suspected')).toHaveLength(0)
    expect(results).toHaveLength(1)
    expect(results[0]!.kind).toBe('ambiguous')
    const conflict = results[0] as Extract<VariantMatchResult, { kind: 'ambiguous' }>
    expect(conflict.reviewRelevant).toBe(true)
    expect([...conflict.leftIds].sort()).toEqual(['L1weak', 'L2weak', 'Ltop'])
    expect([...conflict.rightIds].sort()).toEqual(['R1', 'R2'])
  })
})

describe('matchVariants — ambiguous (never auto-matched for aggregation)', () => {
  it('flags duplicate-looking variants as ambiguous (2 RIGHT variants both raw_exact-identical to one LEFT)', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD' }), variant('R2', { vehicle: 'Q71', driveType: 'AWD' })]
    const results = matchVariants(left, right)
    expect(results).toHaveLength(1)
    expect(results[0]!.kind).toBe('ambiguous')
    const amb = results[0] as Extract<VariantMatchResult, { kind: 'ambiguous' }>
    expect(amb.reviewRelevant).toBe(true)
    expect([...amb.rightIds].sort()).toEqual(['R1', 'R2'])
  })

  it('flags a genuine score tie (Gleichstand) as ambiguous — both sides, even at a fuzzy stage', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'Allradantrib' })]
    const right = [
      variant('R1', { vehicle: 'Q71', driveType: 'Allradantrieb' }),
      variant('R2', { vehicle: 'Q71', driveType: 'Allradantrieb' }),
    ]
    const results = matchVariants(left, right)
    expect(results).toHaveLength(1)
    expect(results[0]!.kind).toBe('ambiguous')
  })

  it('never emits a matched result for either side of an ambiguous group', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD' }), variant('R2', { vehicle: 'Q71', driveType: 'AWD' })]
    const results = matchVariants(left, right)
    expect(matchedOf(results)).toHaveLength(0)
  })
})

describe('matchVariants — stage 4 structural anchor (tiebreak only, never sole criterion)', () => {
  // Adversarial-review-of-#308 F2: R1 and R2 are dimensionally IDENTICAL
  // duplicates of L1 (a genuine "duplicate-looking variant" shape, same as
  // the ambiguous test above) — they only differ by originalVariantNumber.
  // The anchor CAN pick R1 over R2, but R2 has zero alternative candidate
  // anywhere in the pool: applying the anchor here would silently strand R2
  // as an unrelated 'added' SKU even though it is just as qualified as R1.
  // The anchor must therefore refuse to resolve this tie — both candidates
  // go to `ambiguous` for human review instead (Master-Prompt §9).
  it('does NOT let the structural anchor silently strand an equally-qualified loser with no alternative — becomes ambiguous instead', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD' }, { originalVariantNumber: '5' })]
    const right = [
      variant('R1', { vehicle: 'Q71', driveType: 'AWD' }, { originalVariantNumber: '5' }),
      variant('R2', { vehicle: 'Q71', driveType: 'AWD' }, { originalVariantNumber: '9' }),
    ]
    const results = matchVariants(left, right)
    expect(matchedOf(results)).toHaveLength(0)
    expect(results).toHaveLength(1)
    expect(results[0]!.kind).toBe('ambiguous')
    const amb = results[0] as Extract<VariantMatchResult, { kind: 'ambiguous' }>
    expect(amb.reviewRelevant).toBe(true)
    expect(amb.leftIds).toEqual(['L1'])
    expect([...amb.rightIds].sort()).toEqual(['R1', 'R2'])
  })

  // Same tie shape as above, but this time R2 (the anchor's "loser") has a
  // genuine alternative elsewhere in the pool (L3, at a weaker tier) — the
  // anchor MAY safely resolve L1<->R1 here, because doing so does not strand
  // R2: it goes on to match L3 on its own merit. This is the anchor's
  // legitimate, module-header-documented tiebreak use.
  it('DOES use the structural anchor to resolve a tie when the losing candidate has a genuine alternative elsewhere (F2 fix keeps the anchor safe, not useless)', () => {
    // L3 is dimensionally identical to L1 (also raw_exact-ties with both
    // R1/R2, no originalVariantNumber so the anchor never favors it) — its
    // presence gives R2 (the anchor's "loser" against L1) a genuine
    // alternative claimant, so resolving L1<->R1 via the anchor does not
    // strand R2: it goes on to match L3 on its own merit instead.
    const left = [
      variant('L1', { vehicle: 'Q71', driveType: 'AWD' }, { originalVariantNumber: '5' }),
      variant('L3', { vehicle: 'Q71', driveType: 'AWD' }),
    ]
    const right = [
      variant('R1', { vehicle: 'Q71', driveType: 'AWD' }, { originalVariantNumber: '5' }),
      variant('R2', { vehicle: 'Q71', driveType: 'AWD' }, { originalVariantNumber: '9' }),
    ]
    const results = matchVariants(left, right)
    expect(results.some((r) => r.kind === 'ambiguous')).toBe(false)
    const matched = matchedOf(results)
    expect(matched).toHaveLength(2)
    expect(matched.find((m) => m.leftId === 'L1')).toMatchObject({ rightId: 'R1', stage: 'raw_exact' })
    expect(matched.find((m) => m.leftId === 'L3')).toMatchObject({ rightId: 'R2', stage: 'raw_exact' })
  })

  // Adversarial-review-of-#308 F4: the structural anchor must only compare a
  // volume field against the SAME field on the other side (annual<->annual,
  // peak<->peak, lifetime<->lifetime) — never across semantically different
  // volume kinds. R2's peakVolume happens to equal L1's annualVolume
  // numerically (a spurious cross-field "perfect" match, anchor=1 under the
  // pre-fix `?? peakVolume ?? lifetimeVolume` fallback chain), while R1's
  // annualVolume is merely CLOSE to L1's own annualVolume (a real, if
  // imperfect, annual<->annual signal, anchor ~0.952). The fix must still
  // prefer R1 — the real same-field evidence — over R2's spurious cross-field
  // "perfect" one.
  it('never lets the anchor compare DIFFERENT volume fields across sides (annual vs. peak) — prefers the real same-field match', () => {
    const left = [
      variant('L1', { vehicle: 'Q71', driveType: 'AWD' }, { annualVolume: 1000 }),
      // A second, dimensionally-identical-to-L1 left with no volume at all —
      // gives R2 (the anchor's "loser" against L1) a safe alternative so the
      // F2 stranding guard does not itself force this into `ambiguous`
      // (isolating the F4 behavior under test).
      variant('L3', { vehicle: 'Q71', driveType: 'AWD' }),
    ]
    const right = [
      variant('R1', { vehicle: 'Q71', driveType: 'AWD', region: 'EU' }, { annualVolume: 1050 }),
      variant('R2', { vehicle: 'Q71', driveType: 'AWD', platform: 'MQB' }, { peakVolume: 1000 }),
    ]
    const results = matchVariants(left, right)
    expect(results.some((r) => r.kind === 'ambiguous')).toBe(false)
    const matched = matchedOf(results)
    expect(matched).toHaveLength(2)
    expect(matched.find((m) => m.leftId === 'L1')).toMatchObject({ rightId: 'R1' })
    expect(matched.find((m) => m.leftId === 'L3')).toMatchObject({ rightId: 'R2' })
  })

  it('never uses volume/structural anchor as the SOLE criterion — no shared dimension evidence still means no candidate at all', () => {
    const left = [variant('L1', {}, { annualVolume: 1000, originalVariantNumber: '5' })]
    const right = [variant('R1', {}, { annualVolume: 1000, originalVariantNumber: '5' })]
    const results = matchVariants(left, right)
    expect(matchedOf(results)).toHaveLength(0)
    expect(results.map((r) => r.kind).sort()).toEqual(['unmatched_left', 'unmatched_right'])
  })
})

describe('matchVariants — unmatched (removed/added)', () => {
  it('reports a left variant with no plausible right candidate as unmatched_left ("removed")', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'AWD' })]
    const right: VariantDefinition[] = []
    const results = matchVariants(left, right)
    expect(results).toEqual([{ kind: 'unmatched_left', leftIndex: 0, leftId: 'L1', reason: 'removed' }])
  })

  it('reports a right variant with no plausible left candidate as unmatched_right ("added")', () => {
    const left: VariantDefinition[] = []
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'AWD' })]
    const results = matchVariants(left, right)
    expect(results).toEqual([{ kind: 'unmatched_right', rightIndex: 0, rightId: 'R1', reason: 'added' }])
  })
})

describe('matchVariants — coverage invariant', () => {
  it('covers every left and right index exactly once across all result kinds combined', () => {
    const left = [
      variant('L1', { vehicle: 'Q71', driveType: 'AWD' }),
      variant('L2', { vehicle: 'Q72', driveType: 'RWD' }),
      variant('L3', { vehicle: 'Q73', driveType: 'FWD' }),
    ]
    const right = [
      variant('R1', { vehicle: 'Q71', driveType: 'AWD' }), // exact match to L1
      variant('R2', { vehicle: 'Q99', driveType: 'ZZZ' }), // unrelated -> unmatched_right
      // L2, L3 have no right counterpart -> unmatched_left
    ]
    const results = matchVariants(left, right)
    const seenLeft = new Set<number>()
    const seenRight = new Set<number>()
    for (const r of results) {
      if ('leftIndex' in r) seenLeft.add(r.leftIndex)
      if ('leftIndices' in r) for (const i of r.leftIndices) seenLeft.add(i)
      if ('rightIndex' in r) seenRight.add(r.rightIndex)
      if ('rightIndices' in r) for (const i of r.rightIndices) seenRight.add(i)
    }
    expect(seenLeft).toEqual(new Set([0, 1, 2]))
    expect(seenRight).toEqual(new Set([0, 1]))
  })
})

describe('DEFAULT_VARIANT_MATCH_CONFIG', () => {
  it('stage-2 max confidence stays below stage-1 (raw_exact reserves confidence 1)', () => {
    expect(DEFAULT_VARIANT_MATCH_CONFIG.coreSubsetMaxConfidence).toBeLessThan(1)
  })
  it('stage-3 max confidence stays below stage-2 max (fuzzy is less certain than exact-on-subset)', () => {
    expect(DEFAULT_VARIANT_MATCH_CONFIG.fuzzyMaxConfidence).toBeLessThan(DEFAULT_VARIANT_MATCH_CONFIG.coreSubsetMaxConfidence)
  })

  // Adversarial-review-of-#308 F7: the stage-3 confidence formula's two
  // weights (base + per-unit-of-coverage) must be named, overridable
  // VariantMatchConfig fields — not buried literals — same discipline
  // stage-2's coreSubsetBaseConfidence/coreSubsetCoverageWeight already
  // follow. Proven here by actually overriding them and observing the
  // stage-3 score change accordingly (not just that the fields exist).
  it('stage-3 confidence formula actually reads fuzzyBaseWeight/fuzzyCoverageWeight from config, not hardcoded literals', () => {
    const left = [variant('L1', { vehicle: 'Q71', driveType: 'Allradantrieb' })]
    const right = [variant('R1', { vehicle: 'Q71', driveType: 'Allradantrib' })]
    const defaultResult = matchVariants(left, right)
    const loweredWeightResult = matchVariants(left, right, {
      ...DEFAULT_VARIANT_MATCH_CONFIG,
      fuzzyBaseWeight: 0.3,
      fuzzyCoverageWeight: 0.2,
    })
    const defaultMatch = matchedOf(defaultResult)[0]!
    const loweredMatch = matchedOf(loweredWeightResult)[0]!
    expect(defaultMatch.stage).toBe('fuzzy_label_similarity')
    expect(loweredMatch.stage).toBe('fuzzy_label_similarity')
    expect(loweredMatch.confidence).toBeLessThan(defaultMatch.confidence)
  })
})

// ── Review workflow: matchVariantsWithOverrides ─────────────────────────────

describe('matchVariantsWithOverrides', () => {
  function snapshot(v: VariantDefinition) {
    return { compositeCanonicalKey: v.compositeCanonicalKey, dimensions: v.dimensions }
  }

  it('an active override wins over whatever the automatic cascade would have produced (resolves what would otherwise be a 2x2 ambiguous group)', () => {
    // L1/L2 and R1/R2 are pairwise identical (duplicate-looking) — without
    // any override, matchVariants would report this as a single 2x2
    // 'ambiguous' finding (see the duplicate-looking-variants test above).
    const l1 = variant('L1', { vehicle: 'Q71', driveType: 'AWD' })
    const l2 = variant('L2', { vehicle: 'Q71', driveType: 'AWD' })
    const r1 = variant('R1', { vehicle: 'Q71', driveType: 'AWD' })
    const r2 = variant('R2', { vehicle: 'Q71', driveType: 'AWD' })
    const override: VariantMatchOverride = {
      left: snapshot(l1),
      right: snapshot(r1),
      decision: 'matched',
      note: 'Reviewer confirmed L1 <-> R1.',
      setBy: 'reviewer@example.com',
      setAt: '2026-07-13T00:00:00Z',
    }
    const { results, droppedOverrides } = matchVariantsWithOverrides([l1, l2], [r1, r2], [override])
    expect(droppedOverrides).toHaveLength(0)
    expect(results.some((r) => r.kind === 'ambiguous')).toBe(false)
    const matched = matchedOf(results)
    const overrideMatch = matched.find((m) => m.leftId === 'L1')
    expect(overrideMatch).toMatchObject({ rightId: 'R1', stage: 'manual_override', confidence: 1 })
    // L2/R2 fall through to the automatic cascade on the remainder — with
    // only one candidate left on each side, it resolves cleanly (no longer
    // ambiguous once the override pulled L1/R1 out of contention).
    const autoMatch = matched.find((m) => m.leftId === 'L2')
    expect(autoMatch).toMatchObject({ rightId: 'R2', stage: 'raw_exact' })
  })

  it('an "unmatched" override confirms a left variant has no counterpart, without running it through the auto cascade', () => {
    const l1 = variant('L1', { vehicle: 'Q71', driveType: 'AWD' })
    const r1 = variant('R1', { vehicle: 'Q71', driveType: 'AWD' })
    const override: VariantMatchOverride = {
      left: snapshot(l1),
      right: null,
      decision: 'unmatched',
      note: 'Confirmed removed, not renamed.',
      setBy: 'reviewer@example.com',
      setAt: '2026-07-13T00:00:00Z',
    }
    const { results } = matchVariantsWithOverrides([l1], [r1], [override])
    expect(results.some((r) => r.kind === 'unmatched_left' && r.leftId === 'L1')).toBe(true)
    expect(results.some((r) => r.kind === 'unmatched_right' && r.rightId === 'R1')).toBe(true)
  })

  it('drops an override whose left snapshot no longer identifies any current variant (identity drift) and reports it', () => {
    const l1 = variant('L1', { vehicle: 'Q71', driveType: 'AWD' })
    const r1 = variant('R1', { vehicle: 'Q71', driveType: 'AWD' })
    const driftedSnapshotLeft = { compositeCanonicalKey: 'vehicle=q71|driveType=rwd', dimensions: dims({ vehicle: 'Q71', driveType: 'RWD' }) }
    const override: VariantMatchOverride = {
      left: driftedSnapshotLeft,
      right: snapshot(r1),
      decision: 'matched',
      note: null,
      setBy: 'reviewer@example.com',
      setAt: '2026-07-13T00:00:00Z',
    }
    const { results, droppedOverrides } = matchVariantsWithOverrides([l1], [r1], [override])
    expect(droppedOverrides).toHaveLength(1)
    expect(droppedOverrides[0]!.status).toBe('dropped_on_drift')
    // Falls through to the automatic cascade instead of forcing the drifted pairing.
    expect(matchedOf(results)).toHaveLength(1)
    expect(matchedOf(results)[0]).toMatchObject({ leftId: 'L1', rightId: 'R1', stage: 'raw_exact' })
  })

  it('an already-dropped override is passed through untouched and never re-applied', () => {
    const l1 = variant('L1', { vehicle: 'Q71', driveType: 'AWD' })
    const r1 = variant('R1', { vehicle: 'Q71', driveType: 'AWD' })
    const dropped: VariantMatchOverride = {
      left: snapshot(l1),
      right: snapshot(r1),
      decision: 'matched',
      note: null,
      setBy: 'x',
      setAt: '2026-07-13T00:00:00Z',
      status: 'dropped_on_drift',
    }
    const { results, droppedOverrides } = matchVariantsWithOverrides([l1], [r1], [dropped])
    expect(droppedOverrides).toEqual([dropped])
    // The automatic cascade still runs and matches this raw_exact pair on its own merit.
    expect(matchedOf(results)[0]).toMatchObject({ leftId: 'L1', rightId: 'R1', stage: 'raw_exact' })
  })

  // ── adversarial-review-of-#317 finding 4: ambiguous no-identity variants ──
  //
  // Two "no-identity" ALT variants — no dimension row populated, no variant-
  // code fallback either (real-file cause: two reserved/placeholder columns
  // header-parser.ts never assigns a variant-code value to) — both end up
  // with compositeCanonicalKey === '' AND identical (empty) dimensions, so
  // they are LITERALLY indistinguishable by identity evidence. An override
  // whose `left` snapshot is this exact no-identity shape must never be
  // silently applied to the FIRST such variant (Array.find's old behavior) —
  // it must be reported as a distinct, honest 'dropped_ambiguous_identity',
  // never conflated with genuine drift (0 matches).
  it('drops an override as ambiguous_identity (never applies to the first match) when 2+ current ALT variants share the exact same no-identity snapshot', () => {
    const l1 = variant('Q7X', {}, { compositeCanonicalKey: '', dimensions: {} })
    const l2 = variant('T95', {}, { compositeCanonicalKey: '', dimensions: {} })
    const r1 = variant('R1', { vehicle: 'Q7X', driveType: 'AWD' })
    const override: VariantMatchOverride = {
      left: { compositeCanonicalKey: '', dimensions: {} },
      right: snapshot(r1),
      decision: 'matched',
      note: 'Reviewer intended one specific no-identity slot, but both are indistinguishable.',
      setBy: 'reviewer@example.com',
      setAt: '2026-07-13T00:00:00Z',
    }
    const { results, droppedOverrides } = matchVariantsWithOverrides([l1, l2], [r1], [override])
    expect(droppedOverrides).toHaveLength(1)
    expect(droppedOverrides[0]!.status).toBe('dropped_ambiguous_identity')
    // Never silently forced onto l1 (the first candidate) or l2.
    expect(results.some((r) => r.kind === 'matched' && r.stage === 'manual_override')).toBe(false)
  })

  it('drops an override as ambiguous_identity when the NEU side is the one with 2+ identical no-identity variants', () => {
    const l1 = variant('L1', { vehicle: 'Q7X', driveType: 'AWD' })
    const r1 = variant('Q7X-slot', {}, { compositeCanonicalKey: '', dimensions: {} })
    const r2 = variant('T95-slot', {}, { compositeCanonicalKey: '', dimensions: {} })
    const override: VariantMatchOverride = {
      left: snapshot(l1),
      right: { compositeCanonicalKey: '', dimensions: {} },
      decision: 'matched',
      note: null,
      setBy: 'reviewer@example.com',
      setAt: '2026-07-13T00:00:00Z',
    }
    const { results, droppedOverrides } = matchVariantsWithOverrides([l1], [r1, r2], [override])
    expect(droppedOverrides).toHaveLength(1)
    expect(droppedOverrides[0]!.status).toBe('dropped_ambiguous_identity')
    expect(results.some((r) => r.kind === 'matched' && r.stage === 'manual_override')).toBe(false)
  })
})

// ── adversarial-review-of-#317: shared identity-snapshot helpers ───────────
//
// These are the ONE equality/resolution rule findByIdentitySnapshot,
// matchVariantsWithOverrides, and actions.ts's setter/upsert/clear callers
// all share (module header "hängen zusammen" doctrine) — tested directly
// here so a regression in the shared rule fails fast instead of only
// surfacing indirectly through matchVariantsWithOverrides or (untestable,
// 'use server') actions.ts.
describe('identitySnapshotsEqual / identitySnapshotFor / findAllByIdentitySnapshot', () => {
  it('treats two no-identity (empty key, empty dimensions) snapshots as equal', () => {
    expect(identitySnapshotsEqual({ compositeCanonicalKey: '', dimensions: {} }, { compositeCanonicalKey: '', dimensions: {} })).toBe(true)
  })

  it('does NOT treat two different no-identity-key snapshots with different dimensions as equal', () => {
    const a = { compositeCanonicalKey: '', dimensions: dims({ vehicle: 'Q7X' }) }
    const b = { compositeCanonicalKey: '', dimensions: dims({ vehicle: 'T95' }) }
    expect(identitySnapshotsEqual(a, b)).toBe(false)
  })

  it('identitySnapshotFor round-trips a live variant into a snapshot identitySnapshotsEqual accepts', () => {
    const v = variant('L1', { vehicle: 'Q71', driveType: 'AWD' })
    expect(identitySnapshotsEqual(identitySnapshotFor(v), { compositeCanonicalKey: v.compositeCanonicalKey, dimensions: v.dimensions })).toBe(true)
  })

  it('findAllByIdentitySnapshot returns EVERY matching index, not just the first (the adversarial-review-of-#317 F4 bug: Array.find only returns the first)', () => {
    const l1 = variant('Q7X', {}, { compositeCanonicalKey: '', dimensions: {} })
    const l2 = variant('T95', {}, { compositeCanonicalKey: '', dimensions: {} })
    const l3 = variant('L3', { vehicle: 'Q7X' })
    const matches = findAllByIdentitySnapshot([l1, l2, l3], { compositeCanonicalKey: '', dimensions: {} })
    expect(matches).toEqual([0, 1])
  })

  it('findAllByIdentitySnapshot returns an empty array for genuine drift', () => {
    const l1 = variant('L1', { vehicle: 'Q71', driveType: 'AWD' })
    expect(findAllByIdentitySnapshot([l1], { compositeCanonicalKey: 'vehicle=q71|driveType=rwd', dimensions: dims({ vehicle: 'Q71', driveType: 'RWD' }) })).toEqual([])
  })
})

// ── adversarial-review-of-#317 findings 1 & 2: override persistence helpers
// (actions.ts's upsertVariantMatchOverride/clearVariantMatchOverride now
// delegate to these — tested directly here since actions.ts itself is a
// 'use server' file that cannot export testable pure sync helpers). ────────
describe('replaceOverrideForVariant (finding 2 — resubmit must win, not accumulate)', () => {
  function makeOverride(left: ReturnType<typeof identitySnapshotFor>, note: string): VariantMatchOverride {
    return { left, right: null, decision: 'unmatched', note, setBy: 'reviewer@example.com', setAt: '2026-07-13T00:00:00Z' }
  }

  it('setzen → umentscheiden → recompute → die NEUE Zuordnung gilt (regression for the F2 bug: old bare-key compare never replaced a no-identity override, so BOTH the old and the new override stayed persisted and the first-match-wins cascade kept the OLD decision winning forever)', () => {
    // Q7X is a no-identity (empty compositeCanonicalKey) ALT variant — the
    // exact class of variant the F2 bug affected.
    const q7x = variant('Q7X', { vehicle: 'Q7X' }, { compositeCanonicalKey: '' })
    const first = makeOverride(identitySnapshotFor(q7x), 'first decision')
    const second = makeOverride(identitySnapshotFor(q7x), 'RE-DECIDED — this must win')

    const fixedResult = replaceOverrideForVariant([first], second, identitySnapshotFor(q7x))
    // The old decision must be gone entirely — not just appended alongside
    // the new one (which would let matchVariantsWithOverrides' first-match-
    // wins semantics keep applying the STALE `first` override).
    expect(fixedResult).toHaveLength(1)
    expect(fixedResult[0]!.note).toBe('RE-DECIDED — this must win')

    // End-to-end: matchVariantsWithOverrides, given the correctly-replaced
    // list, actually applies the NEW decision.
    const r1 = variant('R1', { vehicle: 'R1' })
    const matchedOverride: VariantMatchOverride = {
      left: identitySnapshotFor(q7x),
      right: identitySnapshotFor(r1),
      decision: 'matched',
      note: 'RE-DECIDED — this must win',
      setBy: 'reviewer@example.com',
      setAt: '2026-07-13T00:00:00Z',
    }
    const { results } = matchVariantsWithOverrides([q7x], [r1], [matchedOverride])
    expect(matchedOf(results)[0]).toMatchObject({ leftId: 'Q7X', rightId: 'R1', stage: 'manual_override' })
  })

  it('never conflates two DIFFERENT no-identity variants — replacing one leaves the other untouched', () => {
    const q7x = variant('Q7X', { vehicle: 'Q7X' }, { compositeCanonicalKey: '' })
    const t95 = variant('T95', { vehicle: 'T95' }, { compositeCanonicalKey: '' })
    const forQ7x = makeOverride(identitySnapshotFor(q7x), 'decision for Q7X')
    const forT95 = makeOverride(identitySnapshotFor(t95), 'decision for T95 — must survive')
    const resubmittedForQ7x = makeOverride(identitySnapshotFor(q7x), 'Q7X re-decided')

    const next = replaceOverrideForVariant([forQ7x, forT95], resubmittedForQ7x, identitySnapshotFor(q7x))
    expect(next).toHaveLength(2)
    expect(next.find((o) => o.note === 'decision for T95 — must survive')).toBeDefined()
    expect(next.find((o) => o.note === 'Q7X re-decided')).toBeDefined()
    expect(next.find((o) => o.note === 'decision for Q7X')).toBeUndefined()
  })
})

describe('removeActiveOverridesForVariant (finding 1 — clear must fail-closed AND honest for no-identity variants)', () => {
  function makeOverride(left: ReturnType<typeof identitySnapshotFor>, note: string, status?: VariantMatchOverride['status']): VariantMatchOverride {
    return { left, right: null, decision: 'unmatched', note, setBy: 'reviewer@example.com', setAt: '2026-07-13T00:00:00Z', ...(status ? { status } : {}) }
  }

  it('removes an active override for a no-identity variant and reports removedCount 1 (regression for the F1 bug: old bare-key compare skipped removal entirely and still claimed success)', () => {
    const q7x = variant('Q7X', { vehicle: 'Q7X' }, { compositeCanonicalKey: '' })
    const active = makeOverride(identitySnapshotFor(q7x), 'active override on a no-identity variant')

    const { next, removedCount } = removeActiveOverridesForVariant([active], identitySnapshotFor(q7x))
    expect(removedCount).toBe(1)
    expect(next).toHaveLength(0)
  })

  it('reports removedCount 0 (honest no-op, never a false "cleared" claim) when nothing is active for this variant', () => {
    const q7x = variant('Q7X', { vehicle: 'Q7X' }, { compositeCanonicalKey: '' })
    const t95 = variant('T95', { vehicle: 'T95' }, { compositeCanonicalKey: '' })
    const forT95 = makeOverride(identitySnapshotFor(t95), 'unrelated override for a different no-identity variant')

    const { next, removedCount } = removeActiveOverridesForVariant([forT95], identitySnapshotFor(q7x))
    expect(removedCount).toBe(0)
    expect(next).toEqual([forT95])
  })

  it('never removes an already-dropped override (status carried through untouched, not double-counted)', () => {
    const q7x = variant('Q7X', { vehicle: 'Q7X' }, { compositeCanonicalKey: '' })
    const dropped = makeOverride(identitySnapshotFor(q7x), 'already dropped', 'dropped_on_drift')

    const { next, removedCount } = removeActiveOverridesForVariant([dropped], identitySnapshotFor(q7x))
    expect(removedCount).toBe(0)
    expect(next).toEqual([dropped])
  })
})
