// Der V2-Ergebnis-Envelope (Spezifikation Kap. 6, 13, 20; Golden File als Massstab).
//
// Wozu: Der Ergebnis-JSON der App ist bis heute ein Abzug der Web-Ansicht —
// zehn flache Sektionen, deren Namen aus der Anzeigekomponente stammen. Das
// Golden File führt 24 fachliche Bereiche. Die Bausteine für fast alle liegen
// seit den Ausbaustufen davor im Kern; verbunden waren sie nie.
//
// Diese Datei ist der Zusammensetzer. Sie rechnet nichts selbst: Jeder Bereich
// kommt aus dem Modul, das ihn verantwortet, oder er steht ausdrücklich auf
// „nicht berechnet".
//
// **Ein fehlender Bereich fehlt nicht — er sagt, dass er fehlt.** Das ist der
// Unterschied zwischen einem unvollständigen und einem unehrlichen Dokument:
// Wer `material_analysis` nicht findet, weiss nicht, ob es keine Befunde gab
// oder ob niemand hingesehen hat. Deshalb trägt jeder Bereich seinen Zustand
// (Kap. 20, U-04), auch wenn er leer ist.
//
// Pure Funktionen, keine I/O.

import { QAF_COMPARE_ENGINE, sectionStateOf, type SectionState } from './export-envelope'
import type { ValidationResult } from './export-validation'
import type { WaterfallSpec } from './chart-specs'

/** Die Bereiche des Ergebnis-Dokuments, in der Reihenfolge des Golden File. */
export const V2_AREAS = [
  'metadata',
  'input_workbooks',
  'comparison_classification',
  'comparison_methodology',
  'executive_summary',
  'summary_cost_bridge',
  'identity_and_premise_changes',
  'material_analysis',
  'manufacturing_analysis',
  'sbm_tooling_analysis',
  'raw_material_and_risk_analysis',
  'workbook_structure_comparison',
  'reconciliation',
  'data_quality',
  'all_differences',
  'traceability_index',
  'ai_guide',
  'presentation_package',
  'validation',
] as const

export type V2Area = (typeof V2_AREAS)[number]

export interface V2ExportInput {
  /** Was die aufrufende Schicht bereits berechnet hat. Alles Übrige gilt als nicht berechnet. */
  areas: Partial<Record<V2Area, unknown>>
  /** Bereiche, die für diesen Vergleichstyp gar nicht gelten. */
  notApplicable?: readonly V2Area[]
  bridge?: WaterfallSpec
  validation: ValidationResult
  /** Zeitstempel des Laufs — von aussen, damit die Ausgabe reproduzierbar bleibt. */
  generatedAt: string
  schemaVersion?: string
}

export interface V2Export {
  schema_version: string
  generated_at: string
  engine: typeof QAF_COMPARE_ENGINE
  /** Gesamtzustand: `complete`, wenn kein Bereich unberechnet blieb. */
  analysis_status: 'complete' | 'partial'
  /** Zustand je Bereich — auch für die, die Inhalt haben. */
  section_state: Record<V2Area, SectionState>
  areas: Record<V2Area, unknown>
}

const DEFAULT_SCHEMA_VERSION = '2.0'

/**
 * Den Envelope zusammensetzen.
 *
 * Die Bereichsliste ist fest: Ein Dokument, dessen Bereiche je nach Lauf
 * erscheinen und verschwinden, lässt sich zwischen zwei Ständen nicht
 * vergleichen — und genau das ist der Zweck dieses Formats. Was nicht berechnet
 * wurde, steht mit `null` und einem Zustand da (R-22, dieselbe Regel wie bei den
 * Preisblock-Zeilen).
 */
export function buildV2Export(input: V2ExportInput): V2Export {
  const nichtAnwendbar = new Set(input.notApplicable ?? [])

  const section_state = {} as Record<V2Area, SectionState>
  const areas = {} as Record<V2Area, unknown>

  for (const area of V2_AREAS) {
    const inhalt = area === 'validation' ? input.validation : input.areas[area]
    // `undefined` heisst „nicht berechnet", `null` heisst „berechnet, kein
    // Inhalt". Am Schlüssel allein lässt sich das nicht unterscheiden: Wer
    // einen Bereich mit undefined übergibt, meint, dass er ihn nicht hat.
    const berechnet = area === 'validation' || inhalt !== undefined

    section_state[area] = sectionStateOf(inhalt, {
      applicable: !nichtAnwendbar.has(area),
      computed: berechnet,
    })
    areas[area] = inhalt ?? null
  }

  const unberechnet = V2_AREAS.filter((a) => section_state[a].status === 'not_computed')

  return {
    schema_version: input.schemaVersion ?? DEFAULT_SCHEMA_VERSION,
    generated_at: input.generatedAt,
    engine: QAF_COMPARE_ENGINE,
    analysis_status: unberechnet.length === 0 ? 'complete' : 'partial',
    section_state,
    areas,
  }
}

/**
 * Welche Bereiche dieser Lauf schuldig geblieben ist.
 *
 * Für den Aufrufer, der es dem Leser sagen muss — und für den Test, der
 * verhindert, dass ein Rückschritt unbemerkt bleibt.
 */
export function missingAreas(doc: V2Export): V2Area[] {
  return V2_AREAS.filter((a) => doc.section_state[a].status === 'not_computed')
}
