package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/spf13/cobra"

	"git.wntrmute.dev/mc/mc-proxy/internal/config"
	"git.wntrmute.dev/mc/mc-proxy/internal/db"
)

func snapshotCmd() *cobra.Command {
	var (
		configPath string
		outputPath string
	)

	cmd := &cobra.Command{
		Use:   "snapshot",
		Short: "Create a database backup",
		RunE: func(cmd *cobra.Command, args []string) error {
			cfg, err := config.Load(configPath)
			if err != nil {
				return err
			}

			store, err := db.Open(cfg.Database.Path)
			if err != nil {
				return fmt.Errorf("opening database: %w", err)
			}
			defer func() { _ = store.Close() }()

			dataDir := filepath.Dir(cfg.Database.Path)

			if outputPath == "" {
				ts := time.Now().UTC().Format("20060102T150405Z")
				outputPath = filepath.Join(dataDir, "backups", fmt.Sprintf("mc-proxy-%s.db", ts))
			}

			// Validate the output path is within the data directory.
			absOutput, err := filepath.Abs(filepath.Clean(outputPath))
			if err != nil {
				return fmt.Errorf("resolving output path: %w", err)
			}
			absDataDir, err := filepath.Abs(dataDir)
			if err != nil {
				return fmt.Errorf("resolving data directory: %w", err)
			}
			if !strings.HasPrefix(absOutput, absDataDir+string(os.PathSeparator)) {
				return fmt.Errorf("output path must be within the data directory (%s)", absDataDir)
			}

			// Ensure the parent directory exists.
			if err := os.MkdirAll(filepath.Dir(outputPath), 0700); err != nil {
				return fmt.Errorf("creating backup directory: %w", err)
			}

			if err := store.Snapshot(outputPath); err != nil {
				return err
			}

			fmt.Printf("snapshot written to %s\n", outputPath)
			return nil
		},
	}

	cmd.Flags().StringVarP(&configPath, "config", "c", "mc-proxy.toml", "path to configuration file")
	cmd.Flags().StringVarP(&outputPath, "output", "o", "", "output path (default: backups/mc-proxy-<timestamp>.db)")

	return cmd
}
