package formula import ( "encoding/json" "fmt" "strings" ) func coerceString(value any) string { switch v := value.(type) { case nil: return "" case string: return strings.TrimSpace(v) case json.Number: return strings.TrimSpace(v.String()) case float64: if v == float64(int64(v)) { return fmt.Sprintf("%d", int64(v)) } return fmt.Sprintf("%v", v) case bool: if v { return "true" } return "false" case []any: parts := make([]string, 0, len(v)) for _, item := range v { if s := coerceString(item); s != "" { parts = append(parts, s) } } return strings.Join(parts, " → ") case map[string]any: if text, ok := v["text"].(string); ok { return strings.TrimSpace(text) } b, err := json.Marshal(v) if err != nil { return "" } return strings.TrimSpace(string(b)) default: return strings.TrimSpace(fmt.Sprint(v)) } } func coerceStringSlice(value any) []string { switch v := value.(type) { case nil: return nil case string: s := strings.TrimSpace(v) if s == "" { return nil } return []string{s} case []any: out := make([]string, 0, len(v)) for _, item := range v { if s := coerceString(item); s != "" { out = append(out, s) } } return out case []string: out := make([]string, 0, len(v)) for _, item := range v { if s := strings.TrimSpace(item); s != "" { out = append(out, s) } } return out default: if s := coerceString(v); s != "" { return []string{s} } return nil } } func pastedAnalysisFromMap(raw map[string]any) *PastedAnalysis { return &PastedAnalysis{ Summary: coerceString(raw["summary"]), Wins: coerceStringSlice(raw["wins"]), Improvements: coerceStringSlice(raw["improvements"]), Formula: coerceString(raw["formula"]), PostTemplate: coerceString(raw["post_template"]), HookPattern: coerceString(raw["hook_pattern"]), Structure: coerceString(raw["structure"]), ReplicationTips: coerceStringSlice(raw["replication_tips"]), Avoid: coerceStringSlice(raw["avoid"]), } }