// QVS-P4 (KAR-973) real-corpus regression for the 2 new SUMMARY label-scan
// fields (sum_planned_capacity/sum_lot_size) — mandatory deliverable per the
// program's own test-strategy note, same discipline as
// lib/qaf-value-stream/internal/__tests__/mapper.real-files.test.ts and
// lib/qaf-differences/internal/g60/__tests__/detect-g60-corpus-sweep.real-files.test.ts.
//
// Full sweep over EVERY file in qaf-corpus/splits/dev.json (227, the exact
// split reports/qaf-value-stream-corpus-evidence.md's own P1 evidence scan
// used) — not a sample, for the same "a stride sample systematically misses
// whole strata" reason mapper.real-files.test.ts's own header documents.
//
// Expected coverage per the P1 corpus-evidence scan (qvs-evidence-scan.mjs,
// a raw regex header-presence scan, NOT this parser): plannedCapacity
// 221/227 (97%), lotSize 220/227 (97%). MEASURED via this test (actual
// summary-parser.ts label-scan): plannedCapacity 138/227 (61%), lotSize
// 200/227 (88%) as first shipped — a real, understood gap from the P1
// figures, not a bug (root-caused via a throwaway ad-hoc diagnostic, not
// committed):
//   1. The P1 scan matched a BROADER "Kapazität"-root regex across ALL
//      sheets — corpus-evidence.md's own table says so explicitly:
//      "Nebentreffer: SBM-Kapazität je AT, capacity factor in
//      Investment-Sheets" — i.e. its 221 count includes hits on OTHER,
//      unrelated capacity fields, not just sum_planned_capacity. Confirmed
//      empirically: of the 51 dev-split files where "Plankapazität"/"planned
//      capacity" is absent from the Summary sheet, ALL 51 also have no such
//      label ANYWHERE ELSE in the workbook — the P1 scan's extra ~90 hits are
//      a different regex group, not this field.
//   2. The P1 scan was a LABEL-PRESENCE scan, explicitly "kein
//      Extraktions-Versuch" (no extraction attempt) — a file whose
//      Plankapazität cell is genuinely blank (the canonical field is
//      `requirement: "optional"`) counts as "present" there but correctly
//      `null` here. Empirically ~33/227 files have the label exactly once on
//      the Summary sheet with no value within summary-parser.ts's shared
//      MAX_SCAN_RIGHT=6 lookup window (labelScan's ambiguity-collision guard
//      itself never fired — 0 files had >1 match).
//
// Review-Fix 5 (KAR-973 adversarial review, MAJOR — landed AFTER the two
// figures above were first measured): 13-14 of the "found" files in that
// 138/200 count were not real values at all — labelScan had walked past a
// genuinely blank value cell onto a NEIGHBORING SUMMARY_METRIC label's own
// un-colon'd text ("Enthaltene Zölle" / "Enthaltene Verpackung und
// Transport", summary-metrics.ts, column G) that happened to sit inside the
// shared MAX_SCAN_RIGHT=6 window — i.e. the 138/200 figures were inflated by
// mis-extractions, not genuine coverage. summary-parser.ts's new
// `FieldDef.strictValueCheck` guard (opt-in for plannedCapacity/lotSize ONLY
// — see that module for why the 4 KAR-910 fields are deliberately excluded)
// now rejects those candidates. RE-MEASURED after the guard: plannedCapacity
// 124/227 (54.6%), lotSize 195/227 (85.9%) — LOWER than the pre-fix numbers,
// and that is the honest result: the guard removes mis-extractions, it does
// not (and structurally cannot) recover a real value the source file never
// had. plannedCapacity's floor below moves from 0.55 to 0.50 accordingly
// (lotSize's 0.85 floor still holds at 0.859 measured, kept unchanged).
//
// This parser reuses the EXACT SAME summary-parser.ts label-scan mechanism
// the 4 KAR-910 fields (peakVolumeYear/productionStartSop/deliverySite/
// shiftsPerWeek) already ship with — MAX_SCAN_RIGHT and the label-scan
// strategy are SHARED, already-shipped behavior this PR deliberately does
// NOT change for those 4 fields (would be an undocumented behavior change to
// 4 unrelated, already-shipped fields, out of this fix's scope — the SAME
// collision mechanism affects them too, e.g. peakVolumeYear/deliverySite in
// 6/5 of the same cross-section files; tracked as an explicit follow-up KAR,
// not silently bundled here). The measured numbers are real and reported
// honestly here and in the PR body rather than forced to match the P1
// figures or the pre-Fix-5 figures.
//
// Confidentiality discipline (KAR-943): no filename, cell value, or price is
// ever logged/asserted — only aggregate counts across the 227-file sweep.
// Skipped everywhere the confidential corpus is absent (CI, most local
// checkouts).

import { describe, it, expect } from 'vitest'
import { existsSync, readFileSync } from 'node:fs'
import path from 'node:path'
import { loadExcelWorkbook, parseSummarySheetFromWorkbook } from '../workbook-adapter'

const CORPUS_DIR = '/home/aria/work/qaf-corpus'
const QAF_DIR = path.join(CORPUS_DIR, 'incoming/QAFs')
const DEV_SPLIT_PATH = path.join(CORPUS_DIR, 'splits/dev.json')

function errMsg(e: unknown): string {
  return e instanceof Error ? e.message : String(e)
}

describe.skipIf(!existsSync(QAF_DIR) || !existsSync(DEV_SPLIT_PATH))(
  'summary-parser.ts sum_planned_capacity/sum_lot_size — dev-split full sweep (env-gated, QVS-P4/KAR-973)',
  () => {
    it('finds plannedCapacity/lotSize at approximately the P1-scan-reported rate across all 227 dev-split files', async () => {
      const dev = JSON.parse(readFileSync(DEV_SPLIT_PATH, 'utf8')) as Array<{ file: string; stratum: string }>
      expect(dev.length).toBe(227)

      let plannedCapacityFound = 0
      let lotSizeFound = 0
      let loadErrors = 0
      const loadErrorSamples: string[] = []

      for (const { file } of dev) {
        try {
          const buffer = readFileSync(path.join(QAF_DIR, file))
          const excelWb = await loadExcelWorkbook(buffer)
          const { summary } = parseSummarySheetFromWorkbook(excelWb)
          if (summary.plannedCapacity.value !== null) plannedCapacityFound++
          if (summary.lotSize.value !== null) lotSizeFound++
        } catch (e) {
          loadErrors++
          // Reason class only (error message), never the filename — same
          // confidentiality discipline as detect-g60-corpus-sweep's errors[].
          if (loadErrorSamples.length < 5) loadErrorSamples.push(errMsg(e))
        }
      }

      const total = dev.length
      // eslint-disable-next-line no-console -- test-only diagnostic, not app code (console discipline scopes app/components/lib/hooks/config, not vitest specs)
      console.info(
        `[QVS-P4 corpus sweep] plannedCapacity ${plannedCapacityFound}/${total}, lotSize ${lotSizeFound}/${total}, loadErrors ${loadErrors}/${total}` +
          (loadErrorSamples.length ? ` — sample error classes: ${loadErrorSamples.join(' | ')}` : ''),
      )

      // Regression floors set from the MEASURED rate (see module header for
      // the full root-cause breakdown, incl. the Review-Fix 5 labelScan
      // plausibility guard), NOT the P1 scan's 221/220 — those numbers
      // measure label PRESENCE across all sheets with a broader regex, not
      // this field's actual VALUE extraction on the Summary sheet
      // specifically. A floor (not an exact pin) so an unrelated
      // corpus/labelScan change doesn't flake this test, while still
      // catching a real regression (e.g. the label match breaking entirely).
      // plannedCapacity's floor moved 0.55 -> 0.50 after Fix 5 (measured
      // 124/227 = 54.6%, DOWN from the pre-fix 138/227 = 61% — the guard
      // rejects mis-extracted neighboring-label text, so a real, honest drop
      // in reported coverage, not a regression); lotSize's 0.85 floor is
      // unchanged (measured 195/227 = 85.9%, still clears it).
      expect(plannedCapacityFound / total, `plannedCapacity coverage ${plannedCapacityFound}/${total}`).toBeGreaterThanOrEqual(0.5)
      expect(lotSizeFound / total, `lotSize coverage ${lotSizeFound}/${total}`).toBeGreaterThanOrEqual(0.85)
    }, 180_000)
  },
)
