package iace

import "github.com/google/uuid"

// Non-test plumbing for the offline proposer (P2 slice 3): run the engine for a
// narrative and produce the fired patterns + the engine-built hazards/mitigations
// the dedup proposer and GT screen consume. This is the same pipeline the GT
// benchmark tests use, lifted out of test scope so the dev-time CLI can call it.

// universalLifecyclePhases are appended so patterns gated to a specific lifecycle
// (maintenance/cleaning/setup/fault clearing) still fire — the proposer wants the
// full hazard picture, not only normal-operation hazards.
var universalLifecyclePhases = []string{"normal_operation", "maintenance", "cleaning", "setup", "fault_clearing"}

// BuildProposerInput parses a narrative, runs the pattern engine, keeps the
// narrative-relevant patterns, and returns the hazards, mitigations and fired
// patterns. NOTE: it does not apply the CE cyber-category skip, so the proposer
// view may include cyber/AI hazards that the CE log excludes — harmless for the
// GT recall screen (they match no CE ground-truth entry).
func BuildProposerInput(narrative, machineType string, extraMachineTypes []string) ([]Hazard, []Mitigation, []PatternMatch) {
	res := ParseNarrative(narrative, machineType)

	var compIDs, compNames, energyIDs []string
	for _, c := range res.Components {
		if c.Negated {
			continue
		}
		compIDs = append(compIDs, c.LibraryID)
		compNames = append(compNames, c.NameDE)
	}
	for _, e := range res.EnergySources {
		energyIDs = append(energyIDs, e.SourceID)
	}

	machineTypes := append([]string{}, extraMachineTypes...)
	if machineType != "" {
		machineTypes = append(machineTypes, machineType)
	}
	lifecycles := append(append([]string{}, res.LifecyclePhases...), universalLifecyclePhases...)

	out := NewPatternEngine().Match(MatchInput{
		ComponentLibraryIDs: compIDs,
		EnergySourceIDs:     energyIDs,
		LifecyclePhases:     lifecycles,
		CustomTags:          res.CustomTags,
		OperationalStates:   res.OperationalStates,
		StateTransitions:    res.StateTransitions,
		HumanRoles:          res.Roles,
		MachineTypes:        machineTypes,
	})

	kept := make([]PatternMatch, 0, len(out.MatchedPatterns))
	for _, pm := range out.MatchedPatterns {
		if IsPatternRelevant(pm, narrative, compNames) {
			kept = append(kept, pm)
		}
	}
	filtered := *out
	filtered.MatchedPatterns = kept
	hazards, mits := patternsToHazardsAndMitigations(&filtered)
	return hazards, mits, kept
}

// patternsToHazardsAndMitigations converts engine output into the hazard/mitigation
// entities the benchmark + proposer compare on. Simplified vs InitializeProject
// (no risk estimation, no norm refs) — it only needs category/zone/scenario/measures.
func patternsToHazardsAndMitigations(out *MatchOutput) ([]Hazard, []Mitigation) {
	hazards := make([]Hazard, 0, len(out.MatchedPatterns))
	patternToHazard := make(map[string]uuid.UUID, len(out.MatchedPatterns))

	for _, pm := range out.MatchedPatterns {
		cat := ""
		if len(pm.HazardCats) > 0 {
			cat = pm.HazardCats[0]
		}
		lifecycle := ""
		if len(pm.ApplicableLifecycles) > 0 {
			lifecycle = pm.ApplicableLifecycles[0]
		}
		h := Hazard{
			ID:             uuid.New(),
			Name:           pm.ScenarioDE,
			Category:       cat,
			Description:    pm.ScenarioDE,
			Scenario:       pm.ScenarioDE,
			TriggerEvent:   pm.TriggerDE,
			PossibleHarm:   pm.HarmDE,
			AffectedPerson: pm.AffectedDE,
			HazardousZone:  pm.ZoneDE,
			LifecyclePhase: lifecycle,
		}
		if h.Name == "" {
			h.Name = pm.PatternName
		}
		hazards = append(hazards, h)
		patternToHazard[pm.PatternID] = h.ID
	}

	measureNames := make(map[string]string)
	for _, m := range GetProtectiveMeasureLibrary() {
		measureNames[m.ID] = m.Name
	}

	var mitigations []Mitigation
	for _, sm := range out.SuggestedMeasures {
		name := measureNames[sm.MeasureID]
		if name == "" {
			name = sm.MeasureID
		}
		for _, srcPattern := range sm.SourcePatterns {
			hid, ok := patternToHazard[srcPattern]
			if !ok {
				continue
			}
			mitigations = append(mitigations, Mitigation{
				ID:       uuid.New(),
				HazardID: hid,
				Name:     name,
			})
		}
	}
	return hazards, mitigations
}
