// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26

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/moby/moby/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 {
		if stErr, ok := errors.AsType[cli.StatusError](err); ok {
			// 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.New(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") != "",
		},
	}

	// Disable file-completion by default. Most commands and flags should not
	// complete with filenames.
	cmd.CompletionOptions.SetDefaultShellCompDirective(cobra.ShellCompDirectiveNoFileComp)

	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
}
