package handlers import ( "database/sql" "encoding/json" "net/http" "time" ) type MarketingHandler struct { DB *sql.DB } func NewMarketingHandler(db *sql.DB) *MarketingHandler { return &MarketingHandler{DB: db} } type Campaign struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` Type string `json:"type"` Status string `json:"status"` Budget float64 `json:"budget"` Spent float64 `json:"spent"` Currency string `json:"currency"` StartDate *time.Time `json:"start_date"` EndDate *time.Time `json:"end_date"` Metrics map[string]interface{} `json:"metrics"` CreatedAt time.Time `json:"created_at"` } type Content struct { ID string `json:"id"` CampaignID *string `json:"campaign_id"` Title string `json:"title"` Type string `json:"type"` Status string `json:"status"` PublishAt *time.Time `json:"publish_at"` PublishedAt *time.Time `json:"published_at"` URL string `json:"url"` Metrics map[string]interface{} `json:"metrics"` CreatedAt time.Time `json:"created_at"` } func (h *MarketingHandler) ListCampaigns(w http.ResponseWriter, r *http.Request) { status := r.URL.Query().Get("status") if status == "" { status = "active" } rows, err := h.DB.Query(` SELECT id, name, description, type, status, budget, spent, currency, start_date, end_date, metrics, created_at FROM boc_campaigns WHERE status = $1 ORDER BY created_at DESC `, status) if err != nil { writeError(w, http.StatusInternalServerError, "database error") return } defer rows.Close() campaigns := []Campaign{} for rows.Next() { var c Campaign var metrics []byte if err := rows.Scan(&c.ID, &c.Name, &c.Description, &c.Type, &c.Status, &c.Budget, &c.Spent, &c.Currency, &c.StartDate, &c.EndDate, &metrics, &c.CreatedAt); err != nil { continue } json.Unmarshal(metrics, &c.Metrics) campaigns = append(campaigns, c) } writeJSON(w, http.StatusOK, map[string]interface{}{ "campaigns": campaigns, "total": len(campaigns), }) } func (h *MarketingHandler) CreateCampaign(w http.ResponseWriter, r *http.Request) { var req Campaign if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request") return } metrics, _ := json.Marshal(req.Metrics) var id string err := h.DB.QueryRow(` INSERT INTO boc_campaigns (name, description, type, status, budget, currency, start_date, end_date, metrics) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id `, req.Name, req.Description, req.Type, req.Status, req.Budget, req.Currency, req.StartDate, req.EndDate, metrics).Scan(&id) if err != nil { writeError(w, http.StatusInternalServerError, "failed to create campaign") return } writeJSON(w, http.StatusCreated, map[string]interface{}{ "id": id, "message": "Campaign created", }) } func (h *MarketingHandler) ListContent(w http.ResponseWriter, r *http.Request) { status := r.URL.Query().Get("status") if status == "" { status = "all" } var query string var args []interface{} if status == "all" { query = ` SELECT id, campaign_id, title, type, status, publish_at, published_at, url, metrics, created_at FROM boc_content ORDER BY created_at DESC LIMIT 100 ` } else { query = ` SELECT id, campaign_id, title, type, status, publish_at, published_at, url, metrics, created_at FROM boc_content WHERE status = $1 ORDER BY created_at DESC LIMIT 100 ` args = append(args, status) } rows, err := h.DB.Query(query, args...) if err != nil { writeError(w, http.StatusInternalServerError, "database error") return } defer rows.Close() contents := []Content{} for rows.Next() { var c Content var metrics []byte if err := rows.Scan(&c.ID, &c.CampaignID, &c.Title, &c.Type, &c.Status, &c.PublishAt, &c.PublishedAt, &c.URL, &metrics, &c.CreatedAt); err != nil { continue } json.Unmarshal(metrics, &c.Metrics) contents = append(contents, c) } writeJSON(w, http.StatusOK, map[string]interface{}{ "content": contents, "total": len(contents), }) } func (h *MarketingHandler) CreateContent(w http.ResponseWriter, r *http.Request) { var req Content if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request") return } metrics, _ := json.Marshal(req.Metrics) var id string err := h.DB.QueryRow(` INSERT INTO boc_content (campaign_id, title, type, status, publish_at, url, metrics) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id `, req.CampaignID, req.Title, req.Type, req.Status, req.PublishAt, req.URL, metrics).Scan(&id) if err != nil { writeError(w, http.StatusInternalServerError, "failed to create content") return } writeJSON(w, http.StatusCreated, map[string]interface{}{ "id": id, "message": "Content created", }) }