package repository import ( "context" "errors" "strings" "time" "github.com/google/uuid" "github.com/jackc/pgx/v5" ) // CrisisPolicyRow is CrisisCare CrisisPolicy catalog. type CrisisPolicyRow struct { ID uuid.UUID `json:"id"` Code string `json:"code"` Title string `json:"title"` Severity string `json:"severity"` Pattern string `json:"pattern"` Action string `json:"action"` HelplineText *string `json:"helpline_text,omitempty"` Active bool `json:"active"` System bool `json:"system"` UpdatedAt time.Time `json:"updated_at"` } // CrisisMatch is one evaluate hit. type CrisisMatch struct { Code string `json:"code"` Title string `json:"title"` Severity string `json:"severity"` Action string `json:"action"` HelplineText *string `json:"helpline_text,omitempty"` } // ListCrisisPolicies returns policies active-first. func (r *AdminRepo) ListCrisisPolicies(ctx context.Context) ([]CrisisPolicyRow, error) { rows, err := r.Pool.Query(ctx, ` SELECT id, code, title, severity, pattern, action, helpline_text, active, system, updated_at FROM crisis_policies ORDER BY active DESC, severity DESC, code ASC LIMIT 500`) if err != nil { return nil, err } defer rows.Close() var out []CrisisPolicyRow for rows.Next() { var p CrisisPolicyRow if err := rows.Scan( &p.ID, &p.Code, &p.Title, &p.Severity, &p.Pattern, &p.Action, &p.HelplineText, &p.Active, &p.System, &p.UpdatedAt, ); err != nil { return nil, err } out = append(out, p) } return out, rows.Err() } // GetCrisisPolicy loads one policy. func (r *AdminRepo) GetCrisisPolicy(ctx context.Context, id uuid.UUID) (*CrisisPolicyRow, error) { var p CrisisPolicyRow err := r.Pool.QueryRow(ctx, ` SELECT id, code, title, severity, pattern, action, helpline_text, active, system, updated_at FROM crisis_policies WHERE id=$1`, id, ).Scan( &p.ID, &p.Code, &p.Title, &p.Severity, &p.Pattern, &p.Action, &p.HelplineText, &p.Active, &p.System, &p.UpdatedAt, ) if errors.Is(err, pgx.ErrNoRows) { return nil, err } if err != nil { return nil, err } return &p, nil } // EvaluateCrisisPolicies runs substring match preview (ops only). func (r *AdminRepo) EvaluateCrisisPolicies(ctx context.Context, text string) ([]CrisisMatch, error) { policies, err := r.ListCrisisPolicies(ctx) if err != nil { return nil, err } lower := strings.ToLower(text) var out []CrisisMatch for _, p := range policies { if !p.Active || p.Pattern == "" { continue } if strings.Contains(lower, strings.ToLower(p.Pattern)) { out = append(out, CrisisMatch{ Code: p.Code, Title: p.Title, Severity: p.Severity, Action: p.Action, HelplineText: p.HelplineText, }) } } if out == nil { out = []CrisisMatch{} } return out, nil }