package engine import ( "path" "strings" "aiaa-notification-service/internal/model" ) // PickEventRule selects the best enabled rule for an event. // Exact event wins; otherwise glob patterns (* and ?) via path.Match. // Among globs, more literal characters win; ties go to the smaller ID. func PickEventRule(event string, rules []model.Rule) *model.Rule { picked := PickEventRules(event, rules) if len(picked) == 0 { return nil } best := &picked[0] for i := range picked[1:] { if picked[i+1].ID < best.ID { best = &picked[i+1] } } return best } // PickEventRules returns every enabled rule at the winning specificity. // All exact event matches win as a group; otherwise all globs that share // the highest literal-character score. func PickEventRules(event string, rules []model.Rule) []model.Rule { var exact []model.Rule var globs []model.Rule bestScore := -1 for i := range rules { r := rules[i] if r.Enabled == 0 { continue } if r.Event == event { exact = append(exact, r) continue } if !strings.ContainsAny(r.Event, "*?") { continue } ok, err := path.Match(r.Event, event) if err != nil || !ok { continue } score := globSpecificity(r.Event) if score > bestScore { bestScore = score globs = []model.Rule{r} continue } if score == bestScore { globs = append(globs, r) } } if len(exact) > 0 { return exact } return globs } func globSpecificity(pattern string) int { n := 0 for _, r := range pattern { if r != '*' && r != '?' { n++ } } return n }