package machine

import (
	"context"
	"fmt"
	"strings"

	"github.com/spf13/cobra"
	"github.com/superfly/flyctl/api"
	"github.com/superfly/flyctl/flaps"
	"github.com/superfly/flyctl/internal/app"
	"github.com/superfly/flyctl/internal/command"
	"github.com/superfly/flyctl/internal/flag"
	"github.com/superfly/flyctl/iostreams"
)

func newStop() *cobra.Command {
	const (
		short = "Stop one or more Fly machines"
		long  = short + "\n"

		usage = "stop <id> [<id>...]"
	)

	cmd := command.New(usage, short, long, runMachineStop,
		command.RequireSession,
		command.LoadAppNameIfPresent,
	)

	cmd.Args = cobra.MinimumNArgs(1)

	flag.Add(
		cmd,
		flag.App(),
		flag.AppConfig(),
	)

	return cmd
}

func runMachineStop(ctx context.Context) (err error) {
	var (
		io   = iostreams.FromContext(ctx)
		args = flag.Args(ctx)
	)

	for _, machineID := range args {
		fmt.Fprintf(io.Out, "Sending kill signal to machine %s...\n", machineID)

		if err = Stop(ctx, machineID); err != nil {
			return
		}
		fmt.Fprintf(io.Out, "%s has been successfully stopped\n", machineID)
	}
	return
}

func Stop(ctx context.Context, machineID string) (err error) {
	var (
		appName = app.NameFromContext(ctx)
	)

	machineStopInput := api.StopMachineInput{
		ID:      machineID,
		Filters: &api.Filters{},
	}

	app, err := appFromMachineOrName(ctx, machineID, appName)
	if err != nil {
		return fmt.Errorf("could not get app: %w", err)
	}

	flapsClient, err := flaps.New(ctx, app)
	if err != nil {
		return fmt.Errorf("could not make flaps client: %w", err)
	}

	err = flapsClient.Stop(ctx, machineStopInput)
	if err != nil {
		switch {
		case strings.Contains(err.Error(), "not found") && appName != "":
			return fmt.Errorf("machine %s was not found in app %s", machineID, appName)
		default:
			return fmt.Errorf("could not stop machine %s: %w", machineStopInput.ID, err)
		}
	}

	return
}
