package iace

import (
	"strings"
	"sync"
)

// Machine-type family reconciliation for NORM suggestion.
//
// Problem: the C-norm library (norms_library_c_*.go) tags norms with a free-form,
// very fine-grained machine-type vocabulary (~455 keys: "welding_machine",
// "band_saw", "mobile_crane", "stamping_press" ...). The project/dropdown
// vocabulary (machine_types.go) has only 68 canonical keys ("welding", "press",
// "circular_saw", "crane" ...). matchNorm() compares them with exact "==", so a
// "welding" project matched 0 of 605 C-norms, "robotics_cobot" 0, "general_industry"
// 0 — machine-type-based C-norm suggestion was effectively dead for most dropdown
// values.
//
// Fix: canonicalMachineType() folds both the norm key AND the project key into a
// shared canonical family before comparison. A "welding_machine" norm and a
// "welding" project both fold to "welding" → they match. This is applied ONLY in
// matchNorm (norm suggestion is advisory). Pattern gating in patternMatches() is
// left STRICT and untouched — loosening it there could re-introduce the cross-
// domain hazard leaks the domain-gating work eliminated.
//
// Coverage is asymmetric on purpose: only norm keys that are genuine synonyms /
// sub-types of one of the 68 canonical dropdown keys are mapped. Niche norm keys
// with no dropdown counterpart (boiler, centrifuge, carousel ...) stay unmapped —
// no project can select them anyway, so mapping would be dead weight.

// machineTypeSynonyms maps a fine-grained machine-type key (norm side OR a
// canonical sub-type on the project side) to its canonical family key. Curated:
// every entry is a true synonym/sub-type. Deliberate EXCLUSIONS guard against
// false folds — e.g. "pressure_vessel"/"pressure_washer"/"blood_pressure_monitor"
// are NOT presses, "treadmill" is not a mill, "seesaw"/"chainsaw" are not saws,
// "heat_pump" is not the industrial pump dropdown.
var machineTypeSynonyms = map[string]string{
	// ── Welding ──
	"welding_machine": "welding", "arc_welding": "welding", "arc_welder": "welding",
	"resistance_welder": "welding", "mig_welder": "welding", "tig_welder": "welding",
	"gas_welding": "welding", "welding_clamp": "welding", "welding_fume_extractor": "welding",
	"spot_welder": "welding",
	// ── Press (forming) — collapses canonical sub-types too ──
	"mechanical_press": "press", "hydraulic_press": "press", "stamping_press": "press",
	"press_brake": "press", "pneumatic_press": "press", "power_press": "press",
	"forging_press": "press", "punch_press": "press", "eccentric_press": "press",
	"toggle_press": "press", "plastics_press": "press", "pressing_machine": "press",
	// ── Saw (bench/stationary) ──
	"saw": "circular_saw", "panel_saw": "circular_saw", "metal_saw": "circular_saw",
	"miter_saw": "circular_saw", "band_saw": "circular_saw", "bandsaw": "circular_saw",
	"cold_saw": "circular_saw", "crosscut_saw": "circular_saw", "log_saw": "circular_saw",
	"pendulum_saw": "circular_saw", "table_saw": "circular_saw", "tile_saw": "circular_saw",
	"food_saw": "circular_saw", "pneumatic_saw": "circular_saw", "chop_saw": "circular_saw",
	// ── Crane ──
	"mobile_crane": "crane", "overhead_crane": "crane", "gantry_crane": "crane",
	"offshore_crane": "crane", "bridge_crane": "crane", "floating_crane": "crane",
	"hydraulic_crane": "crane", "loader_crane": "crane", "slewing_crane": "crane",
	"tower_crane": "crane", "harbour_crane": "crane", "jib_crane": "crane",
	// ── Hoist ──
	"chain_hoist": "hoist", "construction_hoist": "hoist", "engine_hoist": "hoist",
	"manual_hoist": "hoist", "electric_hoist": "hoist", "wire_rope_hoist": "hoist",
	// ── Lift / elevator ──
	"passenger_lift": "elevator", "goods_lift": "elevator", "lifting_equipment": "lift",
	"lift_table": "lift", "lifting_platform": "lift",
	// ── Conveyor ──
	"conveyor_belt": "conveyor", "conveyor_system": "conveyor", "belt_conveyor": "conveyor",
	"roller_conveyor": "conveyor", "screw_conveyor": "conveyor", "baggage_conveyor": "conveyor",
	"telescopic_conveyor": "conveyor", "vibrating_conveyor": "conveyor", "pneumatic_conveyor": "conveyor",
	"mining_conveyor": "conveyor",
	// ── Robot / cobot ──
	"robot": "robotics_cobot", "industrial_robot": "robotics_cobot", "robot_cell": "robotics_cobot",
	"collaborative_robot": "robotics_cobot", "cobot": "robotics_cobot", "articulated_robot": "robotics_cobot",
	// ── Lathe / turning ──
	"large_lathe": "lathe", "small_lathe": "lathe", "turning_machine": "lathe", "cnc_lathe": "lathe",
	// ── Milling ──
	"milling_machine": "milling",
	// ── Grinding ──
	"grinding_machine": "grinding", "grinder": "grinding", "die_grinder": "grinding",
	"handheld_grinder": "grinding", "pneumatic_grinder": "grinding",
	// ── Drilling ──
	"drilling_machine": "drilling", "horizontal_drill": "drilling", "rotary_percussion_drill": "drilling",
	"drilling_rig": "drilling",
	// ── CNC / machining centre ──
	"machining_center": "machining_centre", "cnc_machine": "cnc", "machining_cell": "machining_centre",
	// ── Textile ──
	"textile_machine": "textile", "weaving_machine": "weaving", "spinning_machine": "spinning",
	"knitting_machine": "knitting", "dyeing_machine": "dyeing",
	// ── Woodworking ──
	"woodworking_machine": "woodworking", "planer": "woodworking", "wood_machine": "woodworking",
	// ── Food processing ──
	"food_machine": "food_processing", "food_cutter": "food_processing", "food_slicer": "food_processing",
	"bakery_machine": "food_processing", "bakery": "food_processing", "dough_machine": "food_processing",
	"bread_slicer": "food_processing", "meat_grinder": "food_processing", "meat_processing": "food_processing",
	// ── Packaging ──
	"packaging_machine": "packaging", "filling_machine": "bottling", "bottling_machine": "bottling",
	// ── Laser ──
	"laser_machine": "laser_device", "laser_cutter": "laser_device", "medical_laser": "laser_device",
	// ── Glass processing / washing ──
	"glass_processing_machine": "glass_processing", "glass_breaking_machine": "glass_processing",
	"glass_cutting_machine": "glass_processing", "glass_drilling_machine": "glass_processing",
	"glass_edge_grinder": "glass_processing", "glass_handling": "glass_processing",
	"glass_laminator": "glass_processing", "glass_tempering_furnace": "glass_processing",
	"glass_tilting_device": "glass_processing", "glass_machine": "glass",
	"glass_washing_machine": "glass_washing",
	// ── Agriculture ──
	"agricultural_machine": "agricultural", "combine_harvester": "combine",
	"sugarcane_harvester": "harvester", "agri_tractor": "tractor",
	// ── Pump (industrial) ──
	"hydraulic_pump": "pump", "vacuum_pump": "pump", "fire_pump": "pump", "coating_pump": "pump",
	// ── Surface treatment / coating ──
	"coating_machine": "surface_treatment", "coating": "surface_treatment",
	"powder_coating": "surface_treatment", "painting_machine": "surface_treatment",
	// ── Printing ──
	"printing_machine": "printing", "printing_press_machine": "printing_press",
	// ── Rotary transfer ──
	"rotary_transfer_machine": "rotary_transfer",
	// ── Medical ──
	"medical_electrical_equipment": "medical_device", "dental_equipment": "medical_device",
	"dental_unit": "medical_device", "ct_scanner": "medical_device", "defibrillator": "medical_device",
	"dialysis_device": "medical_device", "ventilator_device": "ventilator",
	// ── Compressor ──
	"air_compressor": "compressor", "screw_compressor": "compressor",
}

// genericMachineSuffixes are folded off when the remainder is itself a canonical
// dropdown key — auto-covers "<canonical>_machine"/"<canonical>_equipment" pairs
// (welding_machine→welding, playground_equipment→playground) without listing each.
var genericMachineSuffixes = []string{"_machine", "_equipment", "_system", "_unit", "_plant", "_line"}

var (
	canonicalVocabOnce sync.Once
	canonicalVocabSet  map[string]bool
)

func canonicalVocab() map[string]bool {
	canonicalVocabOnce.Do(func() {
		canonicalVocabSet = make(map[string]bool)
		for _, v := range MachineTypeVocabulary() {
			canonicalVocabSet[v.Key] = true
		}
	})
	return canonicalVocabSet
}

// canonicalMachineType folds a machine-type key (norm side or project side) into
// its canonical family so the norm engine can match across the two vocabularies.
// Unknown keys are returned unchanged (exact-match fallback = pre-existing
// behaviour, so a niche norm key never starts matching a wrong project).
func canonicalMachineType(key string) string {
	k := strings.ToLower(strings.TrimSpace(key))
	if k == "" {
		return ""
	}
	if c, ok := machineTypeSynonyms[k]; ok {
		return c
	}
	for _, suf := range genericMachineSuffixes {
		if strings.HasSuffix(k, suf) {
			base := strings.TrimSuffix(k, suf)
			if c, ok := machineTypeSynonyms[base]; ok {
				return c
			}
			if canonicalVocab()[base] {
				return base
			}
		}
	}
	return k
}
