package manager

import (
	"context"
	"encoding"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/docker/cli/cli-plugins/hooks"
	"github.com/docker/cli/cli-plugins/metadata"
	"github.com/spf13/cobra"
)

// Plugin represents a potential plugin with all it's metadata.
type Plugin struct {
	metadata.Metadata

	Name string `json:",omitempty"`
	Path string `json:",omitempty"`

	// Err is non-nil if the plugin failed one of the candidate tests.
	Err error `json:",omitempty"`

	// ShadowedPaths contains the paths of any other plugins which this plugin takes precedence over.
	ShadowedPaths []string `json:",omitempty"`
}

// MarshalJSON implements [json.Marshaler] to handle marshaling the
// [Plugin.Err] field (Go doesn't marshal errors by default).
func (p *Plugin) MarshalJSON() ([]byte, error) {
	type Alias Plugin // avoid recursion

	cp := *p // shallow copy to avoid mutating original

	if cp.Err != nil {
		if _, ok := cp.Err.(encoding.TextMarshaler); !ok {
			cp.Err = &pluginError{cp.Err}
		}
	}

	return json.Marshal((*Alias)(&cp))
}

// pluginCandidate represents a possible plugin candidate, for mocking purposes.
type pluginCandidate interface {
	Path() string
	Metadata() ([]byte, error)
}

// newPlugin determines if the given candidate is valid and returns a
// Plugin.  If the candidate fails one of the tests then `Plugin.Err`
// is set, and is always a `pluginError`, but the `Plugin` is still
// returned with no error. An error is only returned due to a
// non-recoverable error.
func newPlugin(c pluginCandidate, cmds []*cobra.Command) (Plugin, error) {
	path := c.Path()
	if path == "" {
		return Plugin{}, errors.New("plugin candidate path cannot be empty")
	}

	// The candidate listing process should have skipped anything
	// which would fail here, so there are all real errors.
	fullname := filepath.Base(path)
	if fullname == "." {
		return Plugin{}, fmt.Errorf("unable to determine basename of plugin candidate %q", path)
	}
	var err error
	if fullname, err = trimExeSuffix(fullname); err != nil {
		return Plugin{}, fmt.Errorf("plugin candidate %q: %w", path, err)
	}
	if !strings.HasPrefix(fullname, metadata.NamePrefix) {
		return Plugin{}, fmt.Errorf("plugin candidate %q: does not have %q prefix", path, metadata.NamePrefix)
	}

	p := Plugin{
		Name: strings.TrimPrefix(fullname, metadata.NamePrefix),
		Path: path,
	}

	// Now apply the candidate tests, so these update p.Err.
	if !isValidPluginName(p.Name) {
		p.Err = newPluginError("plugin candidate %q did not match %q", p.Name, pluginNameFormat)
		return p, nil
	}

	for _, cmd := range cmds {
		// Ignore conflicts with commands which are
		// just plugin stubs (i.e. from a previous
		// call to AddPluginCommandStubs).
		if IsPluginCommand(cmd) {
			continue
		}
		if cmd.Name() == p.Name {
			p.Err = newPluginError("plugin %q duplicates builtin command", p.Name)
			return p, nil
		}
		if cmd.HasAlias(p.Name) {
			p.Err = newPluginError("plugin %q duplicates an alias of builtin command %q", p.Name, cmd.Name())
			return p, nil
		}
	}

	// We are supposed to check for relevant execute permissions here. Instead we rely on an attempt to execute.
	meta, err := c.Metadata()
	if err != nil {
		p.Err = wrapAsPluginError(err, "failed to fetch metadata")
		return p, nil
	}

	if err := json.Unmarshal(meta, &p.Metadata); err != nil {
		p.Err = wrapAsPluginError(err, "invalid metadata")
		return p, nil
	}
	if err := validateSchemaVersion(p.Metadata.SchemaVersion); err != nil {
		p.Err = &pluginError{cause: err}
		return p, nil
	}
	if p.Metadata.Vendor == "" {
		p.Err = newPluginError("plugin metadata does not define a vendor")
		return p, nil
	}
	return p, nil
}

// validateSchemaVersion validates if the plugin's schemaVersion is supported.
//
// The current schema-version is "0.1.0", but we don't want to break compatibility
// until v2.0.0 of the schema version. Check for the major version to be < 2.0.0.
//
// Note that CLI versions before 28.4.1 may not support these versions as they were
// hard-coded to only accept "0.1.0".
func validateSchemaVersion(version string) error {
	if version == "0.1.0" {
		return nil
	}
	if version == "" {
		return errors.New("plugin SchemaVersion version cannot be empty")
	}
	major, _, ok := strings.Cut(version, ".")
	majorVersion, err := strconv.Atoi(major)
	if !ok || err != nil {
		return fmt.Errorf("plugin SchemaVersion %q has wrong format: must be <major>.<minor>.<patch>", version)
	}
	if majorVersion > 1 {
		return fmt.Errorf("plugin SchemaVersion %q is not supported: must be lower than 2.0.0", version)
	}
	return nil
}

// RunHook executes the plugin's hooks command
// and returns its unprocessed output.
func (p *Plugin) RunHook(ctx context.Context, hookData hooks.Request) ([]byte, error) {
	hDataBytes, err := json.Marshal(hookData)
	if err != nil {
		return nil, wrapAsPluginError(err, "failed to marshall hook data")
	}

	pCmd := exec.CommandContext(ctx, p.Path, p.Name, metadata.HookSubcommandName, string(hDataBytes)) // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
	pCmd.Env = os.Environ()
	pCmd.Env = append(pCmd.Env, metadata.ReexecEnvvar+"="+os.Args[0])

	out, err := pCmd.Output()
	if err != nil {
		var exitErr *exec.ExitError
		if errors.As(err, &exitErr) {
			return nil, wrapAsPluginError(err, "plugin hook subcommand exited unsuccessfully")
		}
		return nil, wrapAsPluginError(err, "failed to execute plugin hook subcommand: "+pCmd.String())
	}
	return out, nil
}

// pluginNameFormat is used as part of errors for invalid plugin-names.
// We should consider making this less technical ("must start with "a-z",
// and only consist of lowercase alphanumeric characters").
const pluginNameFormat = `^[a-z][a-z0-9]*$`

func isValidPluginName(s string) bool {
	if len(s) == 0 {
		return false
	}
	// first character must be a-z
	if c := s[0]; c < 'a' || c > 'z' {
		return false
	}
	// followed by a-z or 0-9
	for i := 1; i < len(s); i++ {
		c := s[i]
		if (c < 'a' || c > 'z') && (c < '0' || c > '9') {
			return false
		}
	}
	return true
}
