package iace

// TagResolver resolves component/energy IDs to tags and finds matching
// hazards, measures, and evidence by tag intersection.
type TagResolver struct {
	componentIndex map[string]ComponentLibraryEntry
	energyIndex    map[string]EnergySourceEntry
}

// NewTagResolver creates a TagResolver pre-indexed from the built-in libraries.
func NewTagResolver() *TagResolver {
	tr := &TagResolver{
		componentIndex: make(map[string]ComponentLibraryEntry),
		energyIndex:    make(map[string]EnergySourceEntry),
	}
	for _, c := range GetComponentLibrary() {
		tr.componentIndex[c.ID] = c
	}
	for _, e := range GetEnergySources() {
		tr.energyIndex[e.ID] = e
	}
	return tr
}

// ResolveComponentTags resolves component library IDs to their combined tag set.
func (tr *TagResolver) ResolveComponentTags(componentIDs []string) []string {
	seen := make(map[string]bool)
	var tags []string
	for _, id := range componentIDs {
		comp, ok := tr.componentIndex[id]
		if !ok {
			continue
		}
		for _, tag := range comp.Tags {
			if !seen[tag] {
				seen[tag] = true
				tags = append(tags, tag)
			}
		}
	}
	return tags
}

// ResolveEnergyTags resolves energy source IDs to their combined tag set.
func (tr *TagResolver) ResolveEnergyTags(energyIDs []string) []string {
	seen := make(map[string]bool)
	var tags []string
	for _, id := range energyIDs {
		src, ok := tr.energyIndex[id]
		if !ok {
			continue
		}
		for _, tag := range src.Tags {
			if !seen[tag] {
				seen[tag] = true
				tags = append(tags, tag)
			}
		}
	}
	return tags
}

// ResolveTags combines component, energy, and custom tags into a unified set.
func (tr *TagResolver) ResolveTags(componentIDs, energyIDs, customTags []string) []string {
	seen := make(map[string]bool)
	var all []string

	add := func(tags []string) {
		for _, t := range tags {
			if !seen[t] {
				seen[t] = true
				all = append(all, t)
			}
		}
	}

	add(tr.ResolveComponentTags(componentIDs))
	add(tr.ResolveEnergyTags(energyIDs))
	add(customTags)
	return all
}

// FindHazardsByTags returns hazard library entries that have any matching tag.
func (tr *TagResolver) FindHazardsByTags(tags []string) []HazardLibraryEntry {
	tagSet := toSet(tags)
	var matched []HazardLibraryEntry
	for _, h := range GetBuiltinHazardLibrary() {
		if h.Tags == nil {
			continue
		}
		for _, t := range h.Tags {
			if tagSet[t] {
				matched = append(matched, h)
				break
			}
		}
	}
	return matched
}

// FindMeasuresByTags returns protective measure entries that have any matching tag.
func (tr *TagResolver) FindMeasuresByTags(tags []string) []ProtectiveMeasureEntry {
	tagSet := toSet(tags)
	var matched []ProtectiveMeasureEntry
	for _, m := range GetProtectiveMeasureLibrary() {
		if m.Tags == nil {
			continue
		}
		for _, t := range m.Tags {
			if tagSet[t] {
				matched = append(matched, m)
				break
			}
		}
	}
	return matched
}

// FindEvidenceByTags returns evidence type entries that have any matching tag.
func (tr *TagResolver) FindEvidenceByTags(tags []string) []EvidenceTypeInfo {
	tagSet := toSet(tags)
	var matched []EvidenceTypeInfo
	for _, e := range GetEvidenceTypeLibrary() {
		for _, t := range e.Tags {
			if tagSet[t] {
				matched = append(matched, e)
				break
			}
		}
	}
	return matched
}

// toSet converts a string slice to a map for O(1) lookup.
func toSet(s []string) map[string]bool {
	m := make(map[string]bool, len(s))
	for _, v := range s {
		m[v] = true
	}
	return m
}

// GetEvidenceTypeLibrary returns built-in evidence types with tags for tag resolution.
func GetEvidenceTypeLibrary() []EvidenceTypeInfo {
	return []EvidenceTypeInfo{
		{ID: "E01", Category: "design", LabelDE: "Risikobeurteilung", LabelEN: "Risk Assessment Document", Tags: []string{"design_evidence"}, Sort: 1},
		{ID: "E02", Category: "design", LabelDE: "FMEA-Dokument", LabelEN: "FMEA Document", Tags: []string{"design_evidence", "analysis_evidence"}, Sort: 2},
		{ID: "E03", Category: "design", LabelDE: "Sicherheitskonzept", LabelEN: "Safety Concept", Tags: []string{"design_evidence"}, Sort: 3},
		{ID: "E04", Category: "design", LabelDE: "Schaltplan", LabelEN: "Circuit Diagram", Tags: []string{"design_evidence"}, Sort: 4},
		{ID: "E05", Category: "design", LabelDE: "Hydraulikschaltplan", LabelEN: "Hydraulic Diagram", Tags: []string{"design_evidence"}, Sort: 5},
		{ID: "E06", Category: "design", LabelDE: "Pneumatikschaltplan", LabelEN: "Pneumatic Diagram", Tags: []string{"design_evidence"}, Sort: 6},
		{ID: "E07", Category: "design", LabelDE: "SIL/PL-Berechnung", LabelEN: "SIL/PL Calculation", Tags: []string{"design_evidence", "analysis_evidence"}, Sort: 7},
		{ID: "E08", Category: "test", LabelDE: "Funktionspruefung Schutzeinrichtung", LabelEN: "Guard Function Test", Tags: []string{"test_evidence", "guard_measure"}, Sort: 8},
		{ID: "E09", Category: "test", LabelDE: "Not-Halt-Test", LabelEN: "Emergency Stop Test", Tags: []string{"test_evidence"}, Sort: 9},
		{ID: "E10", Category: "test", LabelDE: "Elektrische Sicherheitspruefung", LabelEN: "Electrical Safety Test", Tags: []string{"test_evidence"}, Sort: 10},
		{ID: "E11", Category: "test", LabelDE: "Druckpruefung", LabelEN: "Pressure Test", Tags: []string{"test_evidence"}, Sort: 11},
		{ID: "E12", Category: "test", LabelDE: "Laermmessung", LabelEN: "Noise Measurement", Tags: []string{"test_evidence"}, Sort: 12},
		{ID: "E13", Category: "test", LabelDE: "Vibrationsmessung", LabelEN: "Vibration Measurement", Tags: []string{"test_evidence"}, Sort: 13},
		{ID: "E14", Category: "test", LabelDE: "Software-Testprotokoll", LabelEN: "Software Test Protocol", Tags: []string{"test_evidence", "software_safety_measure"}, Sort: 14},
		{ID: "E15", Category: "test", LabelDE: "KI-Validierungsbericht", LabelEN: "AI Validation Report", Tags: []string{"test_evidence", "ai_risk"}, Sort: 15},
		{ID: "E16", Category: "cyber", LabelDE: "Penetrationstest-Bericht", LabelEN: "Penetration Test Report", Tags: []string{"cyber_evidence", "test_evidence"}, Sort: 16},
		{ID: "E17", Category: "cyber", LabelDE: "Netzwerk-Segmentierungsnachweis", LabelEN: "Network Segmentation Evidence", Tags: []string{"cyber_evidence"}, Sort: 17},
		{ID: "E18", Category: "cyber", LabelDE: "SBOM (Software Bill of Materials)", LabelEN: "SBOM", Tags: []string{"cyber_evidence"}, Sort: 18},
		{ID: "E19", Category: "cyber", LabelDE: "Patch-Management-Nachweis", LabelEN: "Patch Management Evidence", Tags: []string{"cyber_evidence"}, Sort: 19},
		{ID: "E20", Category: "inspection", LabelDE: "Abnahmeprotokoll", LabelEN: "Acceptance Protocol", Tags: []string{"inspection_evidence"}, Sort: 20},
		{ID: "E21", Category: "inspection", LabelDE: "Wartungscheckliste (ausgefuellt)", LabelEN: "Maintenance Checklist (completed)", Tags: []string{"inspection_evidence", "operational_evidence"}, Sort: 21},
		{ID: "E22", Category: "inspection", LabelDE: "CE-Konformitaetserklaerung", LabelEN: "CE Declaration of Conformity", Tags: []string{"certification_evidence"}, Sort: 22},
		{ID: "E23", Category: "inspection", LabelDE: "Typenpruefzertifikat", LabelEN: "Type Examination Certificate", Tags: []string{"certification_evidence"}, Sort: 23},
		{ID: "E24", Category: "training", LabelDE: "Schulungsnachweis Bediener", LabelEN: "Operator Training Record", Tags: []string{"training_evidence"}, Sort: 24},
		{ID: "E25", Category: "training", LabelDE: "Sicherheitsunterweisung (Protokoll)", LabelEN: "Safety Briefing Record", Tags: []string{"training_evidence"}, Sort: 25},
	}
}
