package iace

// Data-driven self-description of the IACE engine for the "Architektur &
// Datenfluss" explainer. Counts are LIVE (derived from the running engine) so
// the diagram can never drift from reality; the stage/source prose is curated.
// Purpose: let an auditor see WHERE each datum comes from and HOW a risk
// assessment is reached — every gate, library and data source, in order.

// ArchStage is one step of the deterministic pipeline.
type ArchStage struct {
	ID         string `json:"id"`
	Title      string `json:"title"`
	Summary    string `json:"summary"`
	Input      string `json:"input"`
	Logic      string `json:"logic"`
	DataSource string `json:"data_source"` // code/library it draws from
	Example    string `json:"example"`
}

// ArchLibrary is one knowledge base with a LIVE entry count.
type ArchLibrary struct {
	Name        string `json:"name"`
	Count       int    `json:"count"`
	SourceFile  string `json:"source_file"`
	Description string `json:"description"`
}

// ArchDataSource is an external statistic/standard with its license + status.
type ArchDataSource struct {
	Name    string `json:"name"`
	License string `json:"license"`
	Usage   string `json:"usage"`
	Status  string `json:"status"` // "verwendet" | "ausgeschlossen"
}

// Architecture is the full self-description returned by GET /iace/architecture.
type Architecture struct {
	Stages       []ArchStage      `json:"stages"`
	Libraries    []ArchLibrary    `json:"libraries"`
	DataSources  []ArchDataSource `json:"data_sources"`
	NormMatching []string         `json:"norm_matching"`
	Evidence     []RiskEvidence   `json:"evidence"`
}

// distinctDomainGates counts the distinct dom_* capability tags the engine gates on.
func distinctDomainGates() int {
	seen := map[string]bool{}
	for _, tag := range domainGateTerms {
		seen[tag] = true
	}
	return len(seen)
}

// BuildArchitecture assembles the engine self-description with live counts.
func BuildArchitecture() Architecture {
	return Architecture{
		Stages: []ArchStage{
			{
				ID: "grenzen", Title: "1 · Grenzen-Formular",
				Summary:    "Maschinenbeschreibung nach EN ISO 12100 (Verwendungs-, räumliche, zeitliche Grenzen).",
				Input:      "17 Felder: Beschreibung, Verwendung, Fehlanwendung, Schnittstellen (elektrisch/mechanisch/pneumatisch-hydraulisch), Umgebung, Personen …",
				Logic:      "Alle Felder werden zu einer Narrative zusammengeführt (kein Whitelist — jedes Feld ist eine potenzielle Gefährdungsquelle).",
				DataSource: "project.metadata.limits_form",
				Example:    "„Hubantrieb über Kette … 230 V … keine pneumatischen Schnittstellen.“",
			},
			{
				ID: "parse", Title: "2 · ParseNarrative",
				Summary:    "Deterministische Extraktion von Komponenten, Energiequellen, Domänen-Tags und Negationen.",
				Input:      "Narrative-Text + Maschinentyp",
				Logic:      "Keyword-Wörterbuch (Substring, umlaut-normalisiert) → Komponenten + Energie + dom_*-Tags. Negation („keine Pneumatik“) ⇒ Komponente als verneint markiert, liefert KEINE Tags.",
				DataSource: "keyword_dictionary.go",
				Example:    "„Kette“→Komponente, „230 V“→electrical_energy, „Presse“→dom_press.",
			},
			{
				ID: "match", Title: "3 · Pattern-Engine (Gates)",
				Summary:    "Jedes Gefährdungsmuster wird gegen die Maschine geprüft — harte UND-Gates.",
				Input:      "Komponenten-Tags, Energie-Tags, Lebensphasen, Maschinentyp, dom_*-Tags",
				Logic:      "patternMatches: MachineType ∧ Required-Component-Tags ∧ Required-Energy-Tags ∧ Lifecycle ∧ Operational-States. Capability-Domain-Gates (dom_*) verhindern Cross-Domänen-Leaks (z. B. Schwimmbad-Muster feuert nicht für eine Presse). Default-open, wenn ein Gate-Input leer ist.",
				DataSource: "pattern_engine.go + pattern_domain_gates.go + hazard_patterns_*.go",
				Example:    "Presse-Muster feuert nur, wenn machine_type∈Presse-Familie UND high_force-Tag vorhanden.",
			},
			{
				ID: "relevance", Title: "4 · Relevanz-Backstop",
				Summary:    "Generischer Filter gegen Rest-Leaks ungegateter Muster.",
				Input:      "Gefeuertes Muster + Narrative + Komponenten-Namen",
				Logic:      "IsPatternRelevant: Token-Grenzen + Stoppwort-Liste — ein Muster wird verworfen, wenn sein spezifischer Anker nicht in der Narrative vorkommt.",
				DataSource: "pattern_relevance.go",
				Example:    "Verwirft „Bandsäge“-Hazard, wenn die Narrative keine Säge nennt.",
			},
			{
				ID: "caps", Title: "5 · Kategorie-Caps",
				Summary:    "Begrenzung der Gefährdungen je Kategorie (skaliert mit Komponentenzahl).",
				Input:      "Gefeuerte Muster je Gefährdungskategorie",
				Logic:      "categoryHazardCap: pro Kategorie ein Maximum (verhindert Über-Flutung); Dedupe über Kategorie × Zone.",
				DataSource: "iace_handler_init.go",
				Example:    "max. N mechanical_hazard-Gefährdungen je Projekt.",
			},
			{
				ID: "hazards", Title: "6 · Gefährdungen",
				Summary:    "Die erzeugten Gefährdungen (Szenario, Auslöser, Schaden, Zone, betroffene Person).",
				Input:      "Überlebende Muster + zugeordnete Komponente",
				Logic:      "Pro Muster: Szenario/Trigger/Harm/Zone aus dem Muster; Komponentenzuordnung tag-basiert (pickComponentForPattern).",
				DataSource: "iace_hazards (DB)",
				Example:    "„Quetschen im Werkzeugeinbauraum zwischen Ober- und Unterwerkzeug.“",
			},
			{
				ID: "measures", Title: "7 · Maßnahmen",
				Summary:    "Schutzmaßnahmen je Gefährdung — kategorie-gefiltert, KEINE generischen Defaults.",
				Input:      "Gefährdung + musterspezifische Suggested-Measure-IDs",
				Logic:      "Nur Maßnahmen, deren Kategorie zur Gefährdung passt (isCategoryCompatible). Ohne passende Maßnahme ⇒ 0 Maßnahmen + Coverage-Gap (ehrlich, statt Unsinn).",
				DataSource: "measures_library*.go",
				Example:    "Sharp-edge-Gefährdung ⇒ keine „Rotation vermeiden“-Maßnahme.",
			},
			{
				ID: "risk", Title: "8 · Risiko (S/F/W/P + Konfidenz)",
				Summary:    "Konfidenz-bewusste Risikoschätzung je Gefährdung — als Bereich, nicht Punktwert.",
				Input:      "Gefährdungskategorie + Szenario (Kontaktart) + Lebensphasen",
				Logic:      "EstimateSeverity/Frequency/ProbabilityW/AvoidabilityP → R = S×(F+W+P), Band + Bereich (±1 je validierter Genauigkeit) + Konfidenz (Verletzungsmechanismus eindeutig?). W verankert am ESAW-2023-Kontaktmodus-Ranking, Schwere zusätzlich an BLS-CFOI; eigenes Modell, KEINE Norm-Tabelle. Belege durchsuchbar im RAG (bp_iace_accident_stats).",
				DataSource: "risk_estimation.go + risk_data_sources.go (ESAW hsw_ph3_08 2023 + BLS CFOI) + RAG bp_iace_accident_stats",
				Example:    "Elektrischer Schlag: R≈32 (Bereich 21–45, mittel–kritisch), Konfidenz hoch.",
			},
			{
				ID: "norms", Title: "9 · Normen (A/B/C + Familien-Matching)",
				Summary:    "Passende Normen je Maschinentyp und Gefährdung; DIN/ISO/OSHA-Vokabular versöhnt.",
				Input:      "Maschinentyp + Gefährdungskategorien + Tags",
				Logic:      "SuggestNorms: C-Normen exakt per Maschinentyp-FAMILIE (canonicalMachineType: welding_machine→welding); B-Normen per Gefährdungskategorie/Tags; A-Normen gelten immer. Normen werden nur referenziert, Tabellen nie reproduziert.",
				DataSource: "norms_engine.go + machine_type_families.go + norms_library*.go",
				Example:    "Schweißanlage ⇒ EN 60974-x (Lichtbogenschweißen), obwohl Norm auf „welding_machine“ getaggt.",
			},
			{
				ID: "matrix", Title: "10 · Risiko-Matrix / GT-Benchmark",
				Summary:    "Projektweite Risiko-Matrix (Schwere × Wahrscheinlichkeit), Abgleich gegen Experten-GT inkl. Abstands-/Geschwindigkeits-Maße.",
				Input:      "Alle Gefährdungen + (optional) GT-Projekt",
				Logic:      "BuildRiskMatrix aggregiert je Zelle; Benchmark vergleicht Tool-S/F/W/P + Fine-Kinney gegen Fachmann-GT (within±1, Rang-Konkordanz) UND die mm-/mm-s-Maße (CompareDistances: matched / Lücken / Extras + Agreement-%).",
				DataSource: "risk_matrix.go + risk_benchmark.go + distance_benchmark.go",
				Example:    "Kistenhub: Gefährdungs-Coverage hoch; Abstands-Maße nach Lückenfüllung 4/4 (100 %).",
			},
		},
		Libraries: []ArchLibrary{
			{Name: "Hazard-Pattern-Bibliothek", Count: len(AllPatterns()), SourceFile: "hazard_patterns_*.go", Description: "Gefährdungsmuster mit Gates (MachineType/Tags/Energy/Lifecycle) + Szenario/Trigger/Harm/Zone."},
			{Name: "Maßnahmen-Bibliothek", Count: len(GetProtectiveMeasureLibrary()), SourceFile: "measures_library*.go", Description: "Schutzmaßnahmen mit Reduktionstyp + Norm-Referenzen, kategorie-gefiltert."},
			{Name: "Normen-Bibliothek (A/B/C)", Count: len(collectAllNorms()), SourceFile: "norms_library*.go", Description: "A-/B-/C-Normen mit Maschinentypen, Gefährdungskategorien und Tags."},
			{Name: "Komponenten-Bibliothek", Count: len(GetComponentLibrary()), SourceFile: "component_library.go", Description: "Bauteiltypen mit Capability-Tags für das Pattern-Gating."},
			{Name: "Energiequellen", Count: len(GetEnergySources()), SourceFile: "component_library.go", Description: "Energiearten (elektrisch/pneumatisch/hydraulisch …) für Energie-Gates."},
			{Name: "Maschinentyp-Vokabular", Count: len(MachineTypeVocabulary()), SourceFile: "machine_types.go", Description: "Kanonische Dropdown-Maschinentypen, auf die Patterns gaten."},
			{Name: "Domänen-Capability-Gates", Count: distinctDomainGates(), SourceFile: "pattern_domain_gates.go", Description: "dom_*-Tags, die domänenspezifische Muster auf ihre echte Maschine begrenzen (Leak-Schutz)."},
			{Name: "Kontaktmodus-Tiers", Count: len(contactModeTable), SourceFile: "risk_estimation.go", Description: "Verletzungsmechanismen mit W/P/S-Tiers (ESAW-verankert, GT-kalibriert)."},
			{Name: "Kontaktmodus-Evidenz", Count: len(contactModeEvidence), SourceFile: "risk_data_sources.go", Description: "Belegte öffentliche Statistik-Quoten (ESAW) als Zitat-/Audit-Schicht."},
			{Name: "OSHA-Mindestabstände", Count: len(GetOSHAMinimumDistances()), SourceFile: "minimum_distances.go", Description: "OSHA 29 CFR 1910 Sicherheitsabstände (Public Domain) + Maßnahmen-Verknüpfung; EU-Normen nur referenziert."},
		},
		DataSources: []ArchDataSource{
			{Name: "Eurostat ESAW (Kontaktmodus, hsw_ph3_08, 2023)", License: "CC BY 4.0", Usage: "Anker für W-Tiers + zitierbare Quoten → RAG bp_iace_accident_stats", Status: "verwendet"},
			{Name: "US BLS CFOI (tödliche Arbeitsunfälle 2023–24)", License: "Public Domain", Usage: "US-Schwere-Anker (Contact = führend in Manufacturing) → RAG bp_iace_accident_stats", Status: "verwendet"},
			{Name: "OSHA Technical Manual / eTools (Roboter, Mindestabstände)", License: "Public Domain", Usage: "250 mm/s Teach-Anker + 29 CFR 1910 Sicherheitsabstände → minimum_distances.go + RAG bp_iace_safety_kb", Status: "verwendet"},
			{Name: "OPSS PRISM (Severity × Probability Risikomatrix)", License: "Open Government Licence v3", Usage: "Methodik-Anker für S×W → Risiko-Level (RAPEX-aligned) → RAG bp_iace_safety_kb", Status: "verwendet"},
			{Name: "Cobot-Schmerzschwellen (Behrens 2022 / Park 2019)", License: "CC BY 4.0", Usage: "Kraft/Druck-Limits je Körperregion (Daten hinter ISO/TS 15066, nicht die Norm) → RAG bp_iace_safety_kb", Status: "verwendet"},
			{Name: "UK HSE Beispiel-Risikobeurteilungen", License: "Open Government Licence v3", Usage: "qualitative Gefährdung→Maßnahme-Struktur → RAG bp_iace_safety_kb", Status: "verwendet"},
			{Name: "DGUV/IFA-Statistik & -Tabellen", License: "nur redaktionell, keine Bearbeitung", Usage: "—", Status: "ausgeschlossen"},
			{Name: "DIN/Beuth/ISO/IEC Norm- & Risikograph-Tabellen", License: "urheberrechtlich", Usage: "Nur als Referenz genannt, NIE reproduziert (ISO-15066-Werte nur via CC-BY-Papers)", Status: "ausgeschlossen"},
		},
		NormMatching: []string{
			"C-Normen (maschinenspezifisch): Match nur über die kanonische Maschinentyp-FAMILIE — `canonicalMachineType` faltet das feingranulare Normen-Vokabular (455 Keys: welding_machine, band_saw, mobile_crane …) auf die 68 Dropdown-Keys. Ohne Familien-Match wird die C-Norm verworfen (kein Tag/Kategorie-Fallback → keine Fremd-Domänen-Normen).",
			"B-Normen (gefährdungsspezifisch): Match über Gefährdungskategorie und Komponenten-/Energie-Tags.",
			"A-Normen (Grundnormen): gelten immer (z. B. EN ISO 12100).",
			"DIN/ISO/OSHA-Versöhnung: Normen tragen teils OSHA-/ISO-/DIN-nahe Maschinen-Keys; die Familien-Faltung sorgt dafür, dass z. B. eine „welding_machine“-Norm für eine „welding“-Maschine matched.",
			"Lizenz-Leitplanke: Norm-Tabellen/Risikographen werden NIE reproduziert — nur Norm-Referenzen ausgegeben.",
		},
		Evidence: AllRiskEvidence(),
	}
}
