package cli

import (
	_ "embed"
	"fmt"
	"io"
	"os"

	"github.com/spf13/cobra"

	"github.com/tidbcloud/observability/vm-migration/internal/printer"
)

//go:embed templates/plan-template.json
var planTemplateBytes []byte

// InitPlanArgs holds arguments for plan init.
type InitPlanArgs struct {
	Output string
}

// newPlanInitCmd returns the plan init command.
func newPlanInitCmd() *cobra.Command {
	a := &InitPlanArgs{}
	cmd := &cobra.Command{
		Use:   "init",
		Short: "Generate a fresh plan.json from template",
		Long: `Copies the embedded plan-template.json to --output (default: plan.json),
refusing to overwrite.`,
		Args:         cobra.NoArgs,
		SilenceUsage: true,
		Example: `  # Scaffold a fresh plan.json next to your tenants files
  vm-migration plan init

  # Write to a custom path
  vm-migration plan init --output envs/prod-aws-us-east-1/plan.json`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runInitPlan(a, cmd.OutOrStdout())
		},
	}
	cmd.Flags().StringVar(&a.Output, "output", "plan.json", "Path to write plan.json")
	return cmd
}

func runInitPlan(a *InitPlanArgs, stdout io.Writer) error {
	if _, err := os.Stat(a.Output); err == nil {
		return fmt.Errorf("%s already exists; refusing to overwrite. Move it aside first if you want a fresh plan", a.Output)
	} else if !os.IsNotExist(err) {
		return err
	}

	// Written verbatim: a map round-trip would alphabetize the keys and
	// scramble the prepare/migration/decommission step order.
	if err := os.WriteFile(a.Output, planTemplateBytes, 0o600); err != nil {
		return err
	}
	printer.Printf(stdout, "plan init: wrote %s", a.Output)
	printer.Printf(stdout, `    fill in the remaining null fields (all are required except the
    vmctl.rateLimitBytes knob), then run
    vm-migration plan compile --plan-path %s --tenants tenants.json
    to produce a compiled JSON for review.
`, a.Output)
	return nil
}
