package placement

import (
	"strings"
	"testing"

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

func TestPlannerRequirements(t *testing.T) {
	tests := []struct {
		name    string
		raw     string
		want    string
		wantErr bool
	}{
		{name: "explicit image", raw: "image: nixos\n", want: "image/nixos"},
		{name: "explicit default image", raw: "image: default\n", want: "image/default"},
		{name: "explicit json filename", raw: "image: nixos.json\n", want: "image/nixos.json"},
		{name: "explicit arm image", raw: "image: nixos-aarch64\n", want: "image/nixos-aarch64"},
		{name: "omitted image", raw: "steps: []\n", want: DefaultImageCapability},
		{name: "blank image", raw: "image: '  '\n", want: DefaultImageCapability},
		{name: "path", raw: "image: ../nixos\n", wantErr: true},
		{name: "whitespace", raw: "image: 'nixos arm'\n", wantErr: true},
		{name: "wrong yaml type", raw: "image: [nixos]\n", wantErr: true},
		{name: "malformed yaml", raw: "image: [\n", wantErr: true},
	}

	planner := Planner{}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := planner.Requirements(tangled.Pipeline_Workflow{Raw: tt.raw}, tangled.Pipeline{})
			if tt.wantErr {
				if err == nil {
					t.Fatalf("Requirements() = %v, nil; want error", got)
				}
				return
			}
			if err != nil {
				t.Fatalf("Requirements() error = %v", err)
			}
			if len(got) != 1 || got[0] != tt.want {
				t.Fatalf("Requirements() = %v, want [%s]", got, tt.want)
			}
		})
	}
}
func TestDefaultImageCapabilityDoesNotCollideWithExplicitDefault(t *testing.T) {
	explicit, err := ImageCapability("default")
	if err != nil {
		t.Fatal(err)
	}
	if DefaultImageCapability == explicit {
		t.Fatalf("omitted image capability %q collides with explicit image capability", DefaultImageCapability)
	}
	if strings.HasPrefix(DefaultImageCapability, "image/") {
		t.Fatalf("omitted image capability %q is inside the explicit image capability namespace", DefaultImageCapability)
	}
}

func TestIsPlainImageName(t *testing.T) {
	for _, name := range []string{"nixos", "nixos-aarch64", "release.2026_07"} {
		if !IsPlainImageName(name) {
			t.Errorf("IsPlainImageName(%q) = false, want true", name)
		}
	}
	for _, name := range []string{"", ".", "..", "/nixos", "../nixos", `dir\\nixos`, "nixos arm", "nixos\tarm"} {
		if IsPlainImageName(name) {
			t.Errorf("IsPlainImageName(%q) = true, want false", name)
		}
	}
}

func TestIsNativeArchitecture(t *testing.T) {
	tests := []struct {
		image string
		host  string
		want  bool
	}{
		{image: "x86_64", host: "amd64", want: true},
		{image: "amd64", host: "amd64", want: true},
		{image: "aarch64", host: "arm64", want: true},
		{image: "arm64", host: "arm64", want: true},
		{image: "x86_64", host: "arm64", want: false},
		{image: "aarch64", host: "amd64", want: false},
		{image: "", host: "amd64", want: false},
	}
	for _, tt := range tests {
		if got := IsNativeArchitecture(tt.image, tt.host); got != tt.want {
			t.Errorf("IsNativeArchitecture(%q, %q) = %v, want %v", tt.image, tt.host, got, tt.want)
		}
	}
}
