package plugin

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"sync"

	"github.com/docker/cli/cli"
	"github.com/docker/cli/cli-plugins/metadata"
	"github.com/docker/cli/cli-plugins/socket"
	"github.com/docker/cli/cli/command"
	"github.com/docker/cli/cli/connhelper"
	"github.com/docker/cli/cli/debug"
	"github.com/docker/docker/client"
	"github.com/spf13/cobra"
	"go.opentelemetry.io/otel"
)

// PersistentPreRunE must be called by any plugin command (or
// subcommand) which uses the cobra `PersistentPreRun*` hook. Plugins
// which do not make use of `PersistentPreRun*` do not need to call
// this (although it remains safe to do so). Plugins are recommended
// to use `PersistentPreRunE` to enable the error to be
// returned. Should not be called outside of a command's
// PersistentPreRunE hook and must not be run unless Run has been
// called.
var PersistentPreRunE func(*cobra.Command, []string) error

// RunPlugin executes the specified plugin command
func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadata.Metadata) error {
	tcmd := newPluginCommand(dockerCli, plugin, meta)

	var persistentPreRunOnce sync.Once
	PersistentPreRunE = func(cmd *cobra.Command, _ []string) error {
		var retErr error
		persistentPreRunOnce.Do(func() {
			ctx, cancel := context.WithCancel(cmd.Context())
			cmd.SetContext(ctx)
			// Set up the context to cancel based on signalling via CLI socket.
			socket.ConnectAndWait(cancel)

			var opts []command.CLIOption
			if os.Getenv("DOCKER_CLI_PLUGIN_USE_DIAL_STDIO") != "" {
				opts = append(opts, withPluginClientConn(plugin.Name()))
			}
			opts = append(opts, command.WithEnableGlobalMeterProvider(), command.WithEnableGlobalTracerProvider())
			retErr = tcmd.Initialize(opts...)
			ogRunE := cmd.RunE
			if ogRunE == nil {
				ogRun := cmd.Run
				// necessary because error will always be nil here
				// see: https://github.com/golangci/golangci-lint/issues/1379
				//nolint:unparam
				ogRunE = func(cmd *cobra.Command, args []string) error {
					ogRun(cmd, args)
					return nil
				}
				cmd.Run = nil
			}
			cmd.RunE = func(cmd *cobra.Command, args []string) error {
				stopInstrumentation := dockerCli.StartInstrumentation(cmd)
				err := ogRunE(cmd, args)
				stopInstrumentation(err)
				return err
			}
		})
		return retErr
	}

	cmd, args, err := tcmd.HandleGlobalFlags()
	if err != nil {
		return err
	}
	// We've parsed global args already, so reset args to those
	// which remain.
	cmd.SetArgs(args)
	return cmd.Execute()
}

// Run is the top-level entry point to the CLI plugin framework. It should
// be called from the plugin's "main()" function. It initializes a new
// [command.DockerCli] instance with the given options before calling
// makeCmd to construct the plugin command, then invokes the plugin command
// using [RunPlugin].
func Run(makeCmd func(command.Cli) *cobra.Command, meta metadata.Metadata, ops ...command.CLIOption) {
	otel.SetErrorHandler(debug.OTELErrorHandler)

	dockerCLI, err := command.NewDockerCli(ops...)
	if err != nil {
		_, _ = fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	plugin := makeCmd(dockerCLI)

	if err := RunPlugin(dockerCLI, plugin, meta); err != nil {
		var stErr cli.StatusError
		if errors.As(err, &stErr) {
			// StatusError should only be used for errors, and all errors should
			// have a non-zero exit status, so never exit with 0
			if stErr.StatusCode == 0 { // FIXME(thaJeztah): this should never be used with a zero status-code. Check if we do this anywhere.
				stErr.StatusCode = 1
			}
			_, _ = fmt.Fprintln(dockerCLI.Err(), stErr)
			os.Exit(stErr.StatusCode)
		}
		_, _ = fmt.Fprintln(dockerCLI.Err(), err)
		os.Exit(1)
	}
}

func withPluginClientConn(name string) command.CLIOption {
	return func(cli *command.DockerCli) error {
		cmd := "docker"
		if x := os.Getenv(metadata.ReexecEnvvar); x != "" {
			cmd = x
		}
		var flags []string

		// Accumulate all the global arguments, that is those
		// up to (but not including) the plugin's name. This
		// ensures that `docker system dial-stdio` is
		// evaluating the same set of `--config`, `--tls*` etc
		// global options as the plugin was called with, which
		// in turn is the same as what the original docker
		// invocation was passed.
		for _, a := range os.Args[1:] {
			if a == name {
				break
			}
			flags = append(flags, a)
		}
		flags = append(flags, "system", "dial-stdio")

		helper, err := connhelper.GetCommandConnectionHelper(cmd, flags...)
		if err != nil {
			return err
		}
		apiClient, err := client.NewClientWithOpts(client.WithDialContext(helper.Dialer))
		if err != nil {
			return err
		}
		return command.WithAPIClient(apiClient)(cli)
	}
}

func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadata.Metadata) *cli.TopLevelCommand {
	name := plugin.Name()
	fullname := metadata.NamePrefix + name

	cmd := &cobra.Command{
		Use:           fmt.Sprintf("docker [OPTIONS] %s [ARG...]", name),
		Short:         fullname + " is a Docker CLI plugin",
		SilenceUsage:  true,
		SilenceErrors: true,
		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			// We can't use this as the hook directly since it is initialised later (in runPlugin)
			return PersistentPreRunE(cmd, args)
		},
		TraverseChildren:      true,
		DisableFlagsInUseLine: true,
		CompletionOptions: cobra.CompletionOptions{
			DisableDefaultCmd:   false,
			HiddenDefaultCmd:    true,
			DisableDescriptions: os.Getenv("DOCKER_CLI_DISABLE_COMPLETION_DESCRIPTION") != "",
		},
	}
	opts, _ := cli.SetupPluginRootCommand(cmd)

	cmd.SetIn(dockerCli.In())
	cmd.SetOut(dockerCli.Out())
	cmd.SetErr(dockerCli.Err())

	cmd.AddCommand(
		plugin,
		newMetadataSubcommand(plugin, meta),
	)

	visitAll(cmd,
		// prevent adding "[flags]" to the end of the usage line.
		func(c *cobra.Command) { c.DisableFlagsInUseLine = true },
	)

	return cli.NewTopLevelCommand(cmd, dockerCli, opts, cmd.Flags())
}

// visitAll traverses all commands from the root.
func visitAll(root *cobra.Command, fns ...func(*cobra.Command)) {
	for _, cmd := range root.Commands() {
		visitAll(cmd, fns...)
	}
	for _, fn := range fns {
		fn(root)
	}
}

func newMetadataSubcommand(plugin *cobra.Command, meta metadata.Metadata) *cobra.Command {
	if meta.ShortDescription == "" {
		meta.ShortDescription = plugin.Short
	}
	cmd := &cobra.Command{
		Use:    metadata.MetadataSubcommandName,
		Hidden: true,
		// Suppress the global/parent PersistentPreRunE, which
		// needlessly initializes the client and tries to
		// connect to the daemon.
		PersistentPreRun: func(cmd *cobra.Command, args []string) {},
		RunE: func(cmd *cobra.Command, args []string) error {
			enc := json.NewEncoder(os.Stdout)
			enc.SetEscapeHTML(false)
			enc.SetIndent("", "     ")
			return enc.Encode(meta)
		},
	}
	return cmd
}

// RunningStandalone tells a CLI plugin it is run standalone by direct execution
func RunningStandalone() bool {
	if os.Getenv(metadata.ReexecEnvvar) != "" {
		return false
	}
	return len(os.Args) < 2 || os.Args[1] != metadata.MetadataSubcommandName
}
