package campaigns import ( "fmt" "strings" ) // TemplateKey is a seasonal or custom campaign template identifier. type TemplateKey string const ( TemplateChristmas TemplateKey = "christmas" TemplateBlackFriday TemplateKey = "black_friday" TemplateSpring TemplateKey = "spring" TemplateCustom TemplateKey = "custom" ) type Template struct { Key string `json:"key"` Name string `json:"name"` Season string `json:"season"` DefaultSubject string `json:"default_subject"` DefaultPrompt string `json:"default_prompt"` Description string `json:"description"` } var builtInTemplates = []Template{ { Key: string(TemplateChristmas), Name: "Christmas", Season: "christmas", DefaultSubject: "Holiday picks from {{brand}}", DefaultPrompt: "Warm Christmas email for these products. Festive, concise, clear CTA. JSON only.", Description: "Festive seasonal campaign for holiday shoppers.", }, { Key: string(TemplateBlackFriday), Name: "Black Friday", Season: "black_friday", DefaultSubject: "Black Friday deals from {{brand}}", DefaultPrompt: "Urgent Black Friday email for these products. Limited-time value, no false claims, strong CTA. JSON only.", Description: "Deal-focused Black Friday / Cyber Week campaign.", }, { Key: string(TemplateSpring), Name: "Spring", Season: "spring", DefaultSubject: "Fresh for spring — {{brand}}", DefaultPrompt: "Light spring email for these products. Renewal + practical benefits, clear CTA. JSON only.", Description: "Seasonal spring refresh campaign.", }, { Key: string(TemplateCustom), Name: "Custom", Season: "custom", DefaultSubject: "News from {{brand}}", DefaultPrompt: "Clear marketing email for these products. Short subject, scannable body, CTA. JSON only.", Description: "Blank slate with sensible defaults.", }, } func ListTemplates() []Template { out := make([]Template, len(builtInTemplates)) copy(out, builtInTemplates) return out } func GetTemplate(key string) (Template, error) { key = strings.TrimSpace(strings.ToLower(key)) if key == "" { key = string(TemplateCustom) } for _, t := range builtInTemplates { if t.Key == key { return t, nil } } return Template{}, ErrInvalidTemplate } func ValidTemplateKey(key string) bool { _, err := GetTemplate(key) return err == nil } func renderSubject(tpl Template, brand string) string { if brand == "" { brand = "our store" } return strings.ReplaceAll(tpl.DefaultSubject, "{{brand}}", brand) } func templateHTML(subject, intro, productBlock, ctaURL, logoURL string) string { if ctaURL == "" { ctaURL = "#" } logoBlock := "" if strings.TrimSpace(logoURL) != "" { logoBlock = fmt.Sprintf( `

`, escapeAttr(logoURL), ) } return fmt.Sprintf(` %s

%s

%s

%s

Shop now

`, logoBlock, escapeHTML(subject), escapeHTML(intro), productBlock, escapeAttr(ctaURL)) } func escapeHTML(s string) string { r := strings.NewReplacer("&", "&", "<", "<", ">", ">", `"`, """) return r.Replace(s) } func escapeAttr(s string) string { return escapeHTML(s) }