package main

import (
	"bytes"
	"strings"
	"testing"
)

func TestRunRootHelp(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"help"}, &stdout, &stderr)
	if rc != 0 {
		t.Fatalf("rc=%d want 0", rc)
	}
	if !strings.Contains(stdout.String(), "bee commands:") {
		t.Fatalf("stdout missing root usage:\n%s", stdout.String())
	}
}

func TestRunNoArgsPrintsUsage(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run(nil, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), "bee commands:") {
		t.Fatalf("stderr missing root usage:\n%s", stderr.String())
	}
}

func TestRunUnknownCommand(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"wat"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), `unknown command "wat"`) {
		t.Fatalf("stderr missing unknown command message:\n%s", stderr.String())
	}
}

func TestRunVersion(t *testing.T) {
	old := Version
	Version = "test-version"
	t.Cleanup(func() { Version = old })

	var stdout, stderr bytes.Buffer
	rc := run([]string{"version"}, &stdout, &stderr)
	if rc != 0 {
		t.Fatalf("rc=%d want 0", rc)
	}
	if strings.TrimSpace(stdout.String()) != "test-version" {
		t.Fatalf("stdout=%q want %q", strings.TrimSpace(stdout.String()), "test-version")
	}
}

func TestBuildLabelUsesVersionAsIs(t *testing.T) {
	old := Version
	Version = "1.2.3"
	t.Cleanup(func() { Version = old })

	if got := buildLabel(); got != "1.2.3" {
		t.Fatalf("buildLabel=%q want %q", got, "1.2.3")
	}
}

func TestRunExportRequiresTarget(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"export"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), "--target is required") {
		t.Fatalf("stderr missing target error:\n%s", stderr.String())
	}
	if !strings.Contains(stderr.String(), "usage: bee export --target <device>") {
		t.Fatalf("stderr missing export usage:\n%s", stderr.String())
	}
}

func TestRunSATUsage(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"sat"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), "usage: bee sat nvidia|memory|storage") {
		t.Fatalf("stderr missing sat usage:\n%s", stderr.String())
	}
}

func TestRunPreflightRejectsExtraArgs(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"preflight", "extra"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), "usage: bee preflight") {
		t.Fatalf("stderr missing preflight usage:\n%s", stderr.String())
	}
}

func TestRunSupportBundleRejectsExtraArgs(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"support-bundle", "extra"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), "usage: bee support-bundle") {
		t.Fatalf("stderr missing support-bundle usage:\n%s", stderr.String())
	}
}

func TestRunHelpForSubcommand(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"help", "export"}, &stdout, &stderr)
	if rc != 0 {
		t.Fatalf("rc=%d want 0", rc)
	}
	if !strings.Contains(stdout.String(), "usage: bee export --target <device>") {
		t.Fatalf("stdout missing export help:\n%s", stdout.String())
	}
}

func TestRunHelpUnknownSubcommand(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"help", "wat"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), `bee help: unknown command "wat"`) {
		t.Fatalf("stderr missing help error:\n%s", stderr.String())
	}
}

func TestRunSATUnknownTarget(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"sat", "amd"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), `unknown target "amd"`) {
		t.Fatalf("stderr missing sat target error:\n%s", stderr.String())
	}
}

func TestRunSATHelp(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"sat", "--help"}, &stdout, &stderr)
	if rc != 0 {
		t.Fatalf("rc=%d want 0", rc)
	}
	if !strings.Contains(stdout.String(), "usage: bee sat nvidia|memory|storage|cpu") {
		t.Fatalf("stdout missing sat help:\n%s", stdout.String())
	}
}

func TestRunSATRejectsExtraArgs(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"sat", "memory", "extra"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), "bee sat: unexpected arguments") {
		t.Fatalf("stderr missing sat error:\n%s", stderr.String())
	}
}

func TestRunAuditInvalidRuntime(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"audit", "--runtime", "bad"}, &stdout, &stderr)
	if rc != 1 {
		t.Fatalf("rc=%d want 1", rc)
	}
}

func TestRunAuditRejectsExtraArgs(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"audit", "extra"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), "usage: bee audit") {
		t.Fatalf("stderr missing audit usage:\n%s", stderr.String())
	}
}

func TestRunExportRejectsExtraArgs(t *testing.T) {
	t.Parallel()

	var stdout, stderr bytes.Buffer
	rc := run([]string{"export", "--target", "/dev/sdb1", "extra"}, &stdout, &stderr)
	if rc != 2 {
		t.Fatalf("rc=%d want 2", rc)
	}
	if !strings.Contains(stderr.String(), "usage: bee export --target <device>") {
		t.Fatalf("stderr missing export usage:\n%s", stderr.String())
	}
}
