package cli

import (
	"bytes"
	"path/filepath"
	"strings"
	"testing"
)

func TestRunVersion(t *testing.T) {
	var stdout, stderr bytes.Buffer
	code := Run([]string{"version"}, &stdout, &stderr)
	if code != 0 {
		t.Fatalf("exit code = %d, want 0 (stderr=%q)", code, stderr.String())
	}
	if got := strings.TrimSpace(stdout.String()); got != "alt dev" {
		t.Errorf("stdout = %q, want \"alt dev\"", got)
	}
}

func TestRunScenarioValidate(t *testing.T) {
	path := filepath.Join("..", "..", "testdata", "operator", "api_connection_smoke.yaml")
	var stdout, stderr bytes.Buffer
	code := Run([]string{"operator", "scenario", "validate", "--file", path}, &stdout, &stderr)
	if code != 0 {
		t.Fatalf("exit code = %d, want 0 (stderr=%q)", code, stderr.String())
	}
	out := stdout.String()
	for _, want := range []string{"scenario=api_connection_smoke", "status=valid", "steps=1"} {
		if !strings.Contains(out, want) {
			t.Errorf("stdout %q missing %q", out, want)
		}
	}
}

func TestRunScenarioValidateParseError(t *testing.T) {
	path := filepath.Join("..", "..", "testdata", "operator", "malformed_scenario.yaml")
	var stdout, stderr bytes.Buffer
	code := Run([]string{"operator", "scenario", "validate", "--file", path}, &stdout, &stderr)
	if code != 2 {
		t.Fatalf("exit code = %d, want 2 (stdout=%q stderr=%q)", code, stdout.String(), stderr.String())
	}
	if !strings.Contains(stdout.String(), "status=parse_error") {
		t.Errorf("stdout %q missing status=parse_error", stdout.String())
	}
}

func TestRunScenarioRunRequiresFlags(t *testing.T) {
	// Missing --file (and --api-url) is a flag/usage error: exit code 2.
	var stdout, stderr bytes.Buffer
	code := Run([]string{"operator", "scenario", "run"}, &stdout, &stderr)
	if code != 2 {
		t.Fatalf("exit code = %d, want 2 (stderr=%q)", code, stderr.String())
	}
}

func TestRunScenarioRunParseError(t *testing.T) {
	path := filepath.Join("..", "..", "testdata", "operator", "malformed_scenario.yaml")
	var stdout, stderr bytes.Buffer
	code := Run([]string{"operator", "scenario", "run", "--file", path, "--api-url", "ws://127.0.0.1:8080/socket"}, &stdout, &stderr)
	if code != 2 {
		t.Fatalf("exit code = %d, want 2 (stdout=%q stderr=%q)", code, stdout.String(), stderr.String())
	}
	if !strings.Contains(stdout.String(), "status=parse_error") {
		t.Errorf("stdout %q missing status=parse_error", stdout.String())
	}
}

func TestRunScenarioRunTransportFailure(t *testing.T) {
	// Port 1 is closed for inbound app traffic on localhost, so the dial fails
	// before any typed response and the run reports a transport error.
	path := filepath.Join("..", "..", "testdata", "operator", "api_connection_smoke.yaml")
	var stdout, stderr bytes.Buffer
	code := Run([]string{"operator", "scenario", "run", "--file", path, "--api-url", "ws://127.0.0.1:1/socket", "--timeout", "2s"}, &stdout, &stderr)
	if code != 3 {
		t.Fatalf("exit code = %d, want 3 (stdout=%q stderr=%q)", code, stdout.String(), stderr.String())
	}
	if !strings.Contains(stdout.String(), "status=transport_error") {
		t.Errorf("stdout %q missing status=transport_error", stdout.String())
	}
}
