package api

import (
	"archive/zip"
	"bytes"
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"time"
)

// BackupHandler serves GET /api/v1/backup.
// It returns a zip containing config.json, users.json, miner.db, and a
// backup-info.txt with the timestamp and server version.  The caller must
// already be authenticated via basicAuthMiddleware (registered in router.go).
type BackupHandler struct {
	dataDir       string
	serverVersion string
}

// NewBackupHandler creates a BackupHandler for the given data directory.
func NewBackupHandler(dataDir, serverVersion string) *BackupHandler {
	return &BackupHandler{dataDir: dataDir, serverVersion: serverVersion}
}

func (h *BackupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	now := time.Now().UTC()
	dateTag := now.Format("2006-01-02")

	var buf bytes.Buffer
	zw := zip.NewWriter(&buf)

	// backup-info.txt
	info := fmt.Sprintf("AetherForge Deck Backup\nTimestamp: %s\nVersion: %s\n",
		now.Format(time.RFC3339), h.serverVersion)
	if fw, err := zw.Create("backup-info.txt"); err == nil {
		_, _ = fw.Write([]byte(info))
	}

	// Helper: add a file from disk into the zip, skip gracefully if missing.
	addFile := func(name, diskPath string) {
		data, err := os.ReadFile(diskPath)
		if err != nil {
			return
		}
		fw, err := zw.Create(name)
		if err != nil {
			return
		}
		_, _ = fw.Write(data)
	}

	addFile("config.json", filepath.Join(h.dataDir, "config.json"))
	addFile("users.json", filepath.Join(h.dataDir, "users.json"))
	addFile("miner.db", filepath.Join(h.dataDir, "miner.db"))

	if err := zw.Close(); err != nil {
		http.Error(w, "Failed to create backup zip", http.StatusInternalServerError)
		return
	}

	filename := fmt.Sprintf("aetherforge-backup-%s.zip", dateTag)
	w.Header().Set("Content-Type", "application/zip")
	w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
	w.Header().Set("Content-Length", fmt.Sprintf("%d", buf.Len()))
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(buf.Bytes())
}
