package handler import ( "encoding/json" "fmt" "time" "spider/internal/model" "spider/internal/store" "github.com/gin-gonic/gin" ) // BackupHandler handles database backup/export. type BackupHandler struct { store *store.Store } // ExportJSON handles GET /backup/export — exports all core data as JSON. func (h *BackupHandler) ExportJSON(c *gin.Context) { db := h.store.DB var merchants []model.MerchantClean db.Find(&merchants) var merchantsRaw []model.MerchantRaw db.Find(&merchantsRaw) var keywords []model.Keyword db.Find(&keywords) var channels []model.Channel db.Find(&channels) var schedules []model.ScheduleJob db.Find(&schedules) var users []model.User db.Find(&users) // Clear passwords from export for i := range users { users[i].Password = "" } var notes []model.MerchantNote db.Find(¬es) var permissions []model.RolePermission db.Find(&permissions) backup := map[string]interface{}{ "exported_at": time.Now().Format(time.RFC3339), "merchants_clean": merchants, "merchants_raw": merchantsRaw, "keywords": keywords, "channels": channels, "schedules": schedules, "users": users, "merchant_notes": notes, "role_permissions": permissions, } data, _ := json.MarshalIndent(backup, "", " ") filename := fmt.Sprintf("spider-backup-%s.json", time.Now().Format("2006-01-02")) c.Header("Content-Type", "application/json") c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename)) c.Writer.Write(data) LogAudit(h.store, c, "export", "backup", "", nil) } // Stats handles GET /backup/stats — returns table row counts for backup estimation. func (h *BackupHandler) Stats(c *gin.Context) { db := h.store.DB tables := []struct { Name string Model interface{} }{ {"merchants_clean", &model.MerchantClean{}}, {"merchants_raw", &model.MerchantRaw{}}, {"keywords", &model.Keyword{}}, {"channels", &model.Channel{}}, {"task_logs", &model.TaskLog{}}, {"task_details", &model.TaskDetail{}}, {"audit_logs", &model.AuditLog{}}, {"merchant_notes", &model.MerchantNote{}}, {"users", &model.User{}}, {"schedules", &model.ScheduleJob{}}, } result := make([]gin.H, 0, len(tables)) for _, t := range tables { var count int64 db.Model(t.Model).Count(&count) result = append(result, gin.H{"table": t.Name, "rows": count}) } OK(c, result) }