package manager

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

	"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 HookPluginData) ([]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])
	hookCmdOutput, err := pCmd.Output()
	if err != nil {
		return nil, wrapAsPluginError(err, "failed to execute plugin hook subcommand")
	}

	return hookCmdOutput, 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
}
