package app

import (
	"context"
	"errors"
	"fmt"

	"coopcloud.tech/abra/cli/internal"
	"coopcloud.tech/abra/pkg/autocomplete"
	"coopcloud.tech/abra/pkg/client"
	containerPkg "coopcloud.tech/abra/pkg/container"
	"coopcloud.tech/abra/pkg/log"
	"coopcloud.tech/abra/pkg/upstream/container"
	"github.com/docker/cli/cli/command"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/urfave/cli/v3"
)

var user string
var userFlag = &cli.StringFlag{
	Name:        "user",
	Aliases:     []string{"u"},
	Value:       "",
	Destination: &user,
}

var noTTY bool
var noTTYFlag = &cli.BoolFlag{
	Name:        "no-tty",
	Aliases:     []string{"t"},
	Destination: &noTTY,
}

var appRunCommand = cli.Command{
	Name:    "run",
	Aliases: []string{"r"},
	Flags: []cli.Flag{
		noTTYFlag,
		userFlag,
	},
	Before:        internal.SubCommandBefore,
	Usage:         "Run a command in an app service",
	UsageText:     "abra app run <domain> <service> <args> [options]",
	ShellComplete: autocomplete.AppNameComplete,
	HideHelp:      true,
	Action: func(ctx context.Context, cmd *cli.Command) error {
		app := internal.ValidateApp(cmd)

		if cmd.Args().Len() < 2 {
			internal.ShowSubcommandHelpAndError(cmd, errors.New("no <service> provided?"))
		}

		if cmd.Args().Len() < 3 {
			internal.ShowSubcommandHelpAndError(cmd, errors.New("no <args> provided?"))
		}

		cl, err := client.New(app.Server)
		if err != nil {
			log.Fatal(err)
		}

		serviceName := cmd.Args().Get(1)
		stackAndServiceName := fmt.Sprintf("^%s_%s", app.StackName(), serviceName)
		filters := filters.NewArgs()
		filters.Add("name", stackAndServiceName)

		targetContainer, err := containerPkg.GetContainer(context.Background(), cl, filters, false)
		if err != nil {
			log.Fatal(err)
		}

		c := cmd.Args().Slice()[2:]
		execCreateOpts := types.ExecConfig{
			AttachStderr: true,
			AttachStdin:  true,
			AttachStdout: true,
			Cmd:          c,
			Detach:       false,
			Tty:          true,
		}

		if user != "" {
			execCreateOpts.User = user
		}
		if noTTY {
			execCreateOpts.Tty = false
		}

		// FIXME: avoid instantiating a new CLI
		dcli, err := command.NewDockerCli()
		if err != nil {
			log.Fatal(err)
		}

		if _, err := container.RunExec(dcli, cl, targetContainer.ID, &execCreateOpts); err != nil {
			log.Fatal(err)
		}

		return nil
	},
}
