package placement

import (
	"fmt"
	"strings"
	"unicode"

	"gopkg.in/yaml.v3"

	"tangled.org/core/api/tangled"
)

const DefaultImageCapability = "image/default"

type Planner struct{}

func (Planner) Requirements(twf tangled.Pipeline_Workflow, _ tangled.Pipeline) ([]string, error) {
	var manifest struct {
		Image string `yaml:"image"`
	}
	if err := yaml.Unmarshal([]byte(twf.Raw), &manifest); err != nil {
		return nil, fmt.Errorf("parse microVM workflow placement: %w", err)
	}

	image := strings.TrimSpace(manifest.Image)
	if image == "" {
		return []string{DefaultImageCapability}, nil
	}
	capability, err := ImageCapability(image)
	if err != nil {
		return nil, err
	}
	return []string{capability}, nil
}

func ImageCapability(name string) (string, error) {
	name = strings.TrimSpace(name)
	if !IsPlainImageName(name) {
		return "", fmt.Errorf("invalid microVM image name %q: must be a whitespace-free plain name, not a path", name)
	}
	return "image/" + name, nil
}

func IsPlainImageName(name string) bool {
	if name == "" || name == "." || name == ".." {
		return false
	}
	if strings.ContainsAny(name, `/\\`) || strings.ContainsFunc(name, unicode.IsSpace) {
		return false
	}
	return true
}

func IsNativeArchitecture(imageArch, goArch string) bool {
	normalize := func(arch string) string {
		switch arch {
		case "x86_64", "amd64":
			return "amd64"
		case "aarch64", "arm64":
			return "arm64"
		default:
			return arch
		}
	}
	return imageArch != "" && normalize(imageArch) == normalize(goArch)
}
