package manager

import (
	"context"
	"errors"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
	"sync"

	"github.com/containerd/errdefs"
	"github.com/docker/cli/cli-plugins/metadata"
	"github.com/docker/cli/cli/config"
	"github.com/docker/cli/cli/config/configfile"
	"github.com/docker/cli/cli/debug"
	"github.com/fvbommel/sortorder"
	"github.com/spf13/cobra"
	"golang.org/x/sync/errgroup"
)

// errPluginNotFound is the error returned when a plugin could not be found.
type errPluginNotFound string

func (errPluginNotFound) NotFound() {}

func (e errPluginNotFound) Error() string {
	return "Error: No such CLI plugin: " + string(e)
}

// getPluginDirs returns the platform-specific locations to search for plugins
// in order of preference.
//
// Plugin-discovery is performed in the following order of preference:
//
// 1. The "cli-plugins" directory inside the CLIs [config.Path] (usually "~/.docker/cli-plugins").
// 2. Additional plugin directories as configured through [ConfigFile.CLIPluginsExtraDirs].
// 3. Platform-specific defaultSystemPluginDirs.
//
// [ConfigFile.CLIPluginsExtraDirs]: https://pkg.go.dev/github.com/docker/cli@v26.1.4+incompatible/cli/config/configfile#ConfigFile.CLIPluginsExtraDirs
func getPluginDirs(cfg *configfile.ConfigFile) []string {
	var pluginDirs []string

	if cfg != nil {
		pluginDirs = append(pluginDirs, cfg.CLIPluginsExtraDirs...)
	}
	pluginDir := filepath.Join(config.Dir(), "cli-plugins")
	pluginDirs = append(pluginDirs, pluginDir)
	pluginDirs = append(pluginDirs, defaultSystemPluginDirs...)
	return pluginDirs
}

func addPluginCandidatesFromDir(res map[string][]string, d string) {
	dentries, err := os.ReadDir(d)
	// Silently ignore any directories which we cannot list (e.g. due to
	// permissions or anything else) or which is not a directory
	if err != nil {
		return
	}
	for _, dentry := range dentries {
		switch mode := dentry.Type() & os.ModeType; mode { //nolint:exhaustive,nolintlint // no need to include all possible file-modes in this list
		case os.ModeSymlink:
			if !debug.IsEnabled() {
				// Skip broken symlinks unless debug is enabled. With debug
				// enabled, this will print a warning in "docker info".
				if _, err := os.Stat(filepath.Join(d, dentry.Name())); errors.Is(err, os.ErrNotExist) {
					continue
				}
			}
		case 0:
			// Regular file, keep going
		default:
			// Something else, ignore.
			continue
		}
		name := dentry.Name()
		if !strings.HasPrefix(name, metadata.NamePrefix) {
			continue
		}
		name = strings.TrimPrefix(name, metadata.NamePrefix)
		var err error
		if name, err = trimExeSuffix(name); err != nil {
			continue
		}
		res[name] = append(res[name], filepath.Join(d, dentry.Name()))
	}
}

// listPluginCandidates returns a map from plugin name to the list of (unvalidated) Candidates. The list is in descending order of priority.
func listPluginCandidates(dirs []string) map[string][]string {
	result := make(map[string][]string)
	for _, d := range dirs {
		addPluginCandidatesFromDir(result, d)
	}
	return result
}

// GetPlugin returns a plugin on the system by its name
func GetPlugin(name string, dockerCLI config.Provider, rootcmd *cobra.Command) (*Plugin, error) {
	pluginDirs := getPluginDirs(dockerCLI.ConfigFile())
	return getPlugin(name, pluginDirs, rootcmd)
}

func getPlugin(name string, pluginDirs []string, rootcmd *cobra.Command) (*Plugin, error) {
	candidates := listPluginCandidates(pluginDirs)
	if paths, ok := candidates[name]; ok {
		if len(paths) == 0 {
			return nil, errPluginNotFound(name)
		}
		c := &candidate{paths[0]}
		p, err := newPlugin(c, rootcmd.Commands())
		if err != nil {
			return nil, err
		}
		if !errdefs.IsNotFound(p.Err) {
			p.ShadowedPaths = paths[1:]
		}
		return &p, nil
	}

	return nil, errPluginNotFound(name)
}

// ListPlugins produces a list of the plugins available on the system
func ListPlugins(dockerCli config.Provider, rootcmd *cobra.Command) ([]Plugin, error) {
	pluginDirs := getPluginDirs(dockerCli.ConfigFile())
	candidates := listPluginCandidates(pluginDirs)
	if len(candidates) == 0 {
		return nil, nil
	}

	var plugins []Plugin
	var mu sync.Mutex
	ctx := rootcmd.Context()
	if ctx == nil {
		// Fallback, mostly for tests that pass a bare cobra.command
		ctx = context.Background()
	}
	eg, _ := errgroup.WithContext(ctx)
	cmds := rootcmd.Commands()
	for _, paths := range candidates {
		func(paths []string) {
			eg.Go(func() error {
				if len(paths) == 0 {
					return nil
				}
				c := &candidate{paths[0]}
				p, err := newPlugin(c, cmds)
				if err != nil {
					return err
				}
				if !errdefs.IsNotFound(p.Err) {
					p.ShadowedPaths = paths[1:]
					mu.Lock()
					defer mu.Unlock()
					plugins = append(plugins, p)
				}
				return nil
			})
		}(paths)
	}
	if err := eg.Wait(); err != nil {
		return nil, err
	}

	sort.Slice(plugins, func(i, j int) bool {
		return sortorder.NaturalLess(plugins[i].Name, plugins[j].Name)
	})

	return plugins, nil
}

// PluginRunCommand returns an [os/exec.Cmd] which when [os/exec.Cmd.Run] will execute the named plugin.
// The rootcmd argument is referenced to determine the set of builtin commands in order to detect conficts.
// The error returned satisfies the [errdefs.IsNotFound] predicate if no plugin was found or if the first candidate plugin was invalid somehow.
func PluginRunCommand(dockerCli config.Provider, name string, rootcmd *cobra.Command) (*exec.Cmd, error) {
	// This uses the full original args, not the args which may
	// have been provided by cobra to our caller. This is because
	// they lack e.g. global options which we must propagate here.
	args := os.Args[1:]
	if !isValidPluginName(name) {
		// We treat this as "not found" so that callers will
		// fallback to their "invalid" command path.
		return nil, errPluginNotFound(name)
	}
	exename := addExeSuffix(metadata.NamePrefix + name)
	pluginDirs := getPluginDirs(dockerCli.ConfigFile())

	for _, d := range pluginDirs {
		path := filepath.Join(d, exename)

		// We stat here rather than letting the exec tell us
		// ENOENT because the latter does not distinguish a
		// file not existing from its dynamic loader or one of
		// its libraries not existing.
		if _, err := os.Stat(path); os.IsNotExist(err) {
			continue
		}

		c := &candidate{path: path}
		plugin, err := newPlugin(c, rootcmd.Commands())
		if err != nil {
			return nil, err
		}
		if plugin.Err != nil {
			// TODO: why are we not returning plugin.Err?
			return nil, errPluginNotFound(name)
		}
		cmd := exec.Command(plugin.Path, args...) // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"

		// Using dockerCli.{In,Out,Err}() here results in a hang until something is input.
		// See: - https://github.com/golang/go/issues/10338
		//      - https://github.com/golang/go/commit/d000e8742a173aa0659584aa01b7ba2834ba28ab
		// os.Stdin is a *os.File which avoids this behaviour. We don't need the functionality
		// of the wrappers here anyway.
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		cmd.Env = append(cmd.Environ(), metadata.ReexecEnvvar+"="+os.Args[0])
		cmd.Env = appendPluginResourceAttributesEnvvar(cmd.Env, rootcmd, plugin)

		return cmd, nil
	}
	return nil, errPluginNotFound(name)
}

// IsPluginCommand checks if the given cmd is a plugin-stub.
func IsPluginCommand(cmd *cobra.Command) bool {
	return cmd.Annotations[metadata.CommandAnnotationPlugin] == "true"
}
