package cli_test

import (
	"context"
	"fmt"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"go.uber.org/zap"

	clipkg "iop/apps/node/internal/adapters/cli"
	"iop/apps/node/internal/adapters/cli/internal/testutil"
	"iop/apps/node/internal/adapters/cli/status"
	noderuntime "iop/apps/node/internal/runtime"
	"iop/packages/go/config"
)

func TestCLIStartPersistentReturnsErrorWhenProcessExitsDuringStartup(t *testing.T) {
	testutil.RequirePTYSupport(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"exits-immediately": {
				Command:              "sh",
				Args:                 []string{"-c", "exit 2"},
				Persistent:           true,
				Terminal:             true,
				StartupIdleTimeoutMS: 50,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())

	if err := c.Start(context.Background()); err == nil {
		t.Fatal("expected error when persistent process exits during startup")
	}
}

func TestCLIStartCleansUpStartedProfilesWhenLaterProfileFails(t *testing.T) {
	testutil.RequireUnixShell(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"ok-profile": {
				Command:               "sh",
				Args:                  []string{"-c", `while IFS= read -r line; do printf "reply:%s\n" "$line"; done`},
				Persistent:            true,
				Terminal:              false,
				StartupIdleTimeoutMS:  50,
				ResponseIdleTimeoutMS: 200,
			},
			"fail-profile": {
				Command:              "sh",
				Args:                 []string{"-c", "exit 2"},
				Persistent:           true,
				Terminal:             true,
				StartupIdleTimeoutMS: 50,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()

	if err := c.Start(ctx); err == nil {
		t.Fatal("expected Start to fail when one persistent profile exits immediately")
	}

	_ = c.Stop(ctx)
	_ = c.Stop(ctx)

	// After rollback, the pre-started default session for ok-profile is gone.
	// Verify with require-existing so lazy creation is not allowed.
	for _, model := range []string{"ok-profile", "fail-profile"} {
		sink := &testutil.FakeSink{}
		if err := c.Execute(ctx, noderuntime.ExecutionSpec{
			RunID:       "post-cleanup",
			Target:      model,
			SessionMode: noderuntime.SessionModeRequireExisting,
			Input:       map[string]any{"prompt": "test"},
		}, sink); err == nil {
			t.Fatalf("expected Execute for %q to fail after cleanup (require-existing), got nil", model)
		}
	}
}

func TestCLIStartDeterministicOrder(t *testing.T) {
	testutil.RequireUnixShell(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"Z-alive": {
				Command:               "sh",
				Args:                  []string{"-c", `while IFS= read -r line; do printf "reply:%s\n" "$line"; done`},
				Persistent:            true,
				Terminal:              false,
				StartupIdleTimeoutMS:  50,
				ResponseIdleTimeoutMS: 200,
			},
			"Z-fail": {
				Command:              "sh",
				Args:                 []string{"-c", "exit 2"},
				Persistent:           true,
				Terminal:             true,
				StartupIdleTimeoutMS: 50,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()

	if err := c.Start(ctx); err == nil {
		t.Fatal("expected Start to fail when one persistent profile exits immediately")
	}

	_ = c.Stop(ctx)
	_ = c.Stop(ctx)

	// After rollback, pre-started default sessions must be gone.
	for _, model := range []string{"Z-alive", "Z-fail"} {
		sink := &testutil.FakeSink{}
		if err := c.Execute(ctx, noderuntime.ExecutionSpec{
			RunID:       "post-cleanup",
			Target:      model,
			SessionMode: noderuntime.SessionModeRequireExisting,
			Input:       map[string]any{"prompt": "test"},
		}, sink); err == nil {
			t.Fatalf("expected Execute for %q to fail after cleanup (require-existing), got nil", model)
		}
	}
}

func TestCLIStartSkipsPersistentLazyProfileAndExecuteCreatesSession(t *testing.T) {
	testutil.RequireUnixShell(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"lazy-echo": {
				Command:               "sh",
				Args:                  []string{"-c", `while IFS= read -r line; do printf "reply:%s\n" "$line"; done`},
				Persistent:            true,
				Terminal:              false,
				ResponseIdleTimeoutMS: 100,
				StartupIdleTimeoutMS:  50,
				Mode:                  "persistent-lazy",
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()

	if err := c.Start(ctx); err != nil {
		t.Fatalf("start should not pre-start persistent-lazy profile: %v", err)
	}
	defer func() { _ = c.Stop(ctx) }()

	requireExistingSink := &testutil.FakeSink{}
	if err := c.Execute(ctx, noderuntime.ExecutionSpec{
		RunID:       "run-require-existing",
		Target:      "lazy-echo",
		SessionMode: noderuntime.SessionModeRequireExisting,
		Input:       map[string]any{"prompt": "hello"},
	}, requireExistingSink); err == nil {
		t.Fatal("expected require-existing execute to fail before lazy session is created")
	}

	sink := &testutil.FakeSink{}
	if err := c.Execute(ctx, noderuntime.ExecutionSpec{
		RunID:  "run-create",
		Target: "lazy-echo",
		Input:  map[string]any{"prompt": "hello"},
	}, sink); err != nil {
		t.Fatalf("execute should create lazy persistent session: %v", err)
	}
	if combined := testutil.CollectDeltas(sink.Events()); !strings.Contains(combined, "reply:hello") {
		t.Fatalf("expected lazy session reply in deltas, got %q", combined)
	}
}

func TestCLIConcurrentExecuteAndStop(t *testing.T) {
	testutil.RequirePTYSupport(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"slow-echo": {
				Command:               "sh",
				Args:                  []string{"-c", `stty -echo; while IFS= read -r line; do sleep 0.05; printf "reply:%s\n" "$line"; done`},
				Persistent:            true,
				Terminal:              true,
				ResponseIdleTimeoutMS: 50,
				StartupIdleTimeoutMS:  50,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())

	ctx := context.Background()
	if err := c.Start(ctx); err != nil {
		t.Fatalf("start: %v", err)
	}

	errCh := make(chan error, 10)
	done := make(chan struct{})

	go func() {
		for i := 0; i < 3; i++ {
			sink := &testutil.FakeSink{}
			execCtx, cancel := context.WithTimeout(ctx, 500*time.Millisecond)
			err := c.Execute(execCtx, noderuntime.ExecutionSpec{
				RunID:  fmt.Sprintf("run-conc-%d", i),
				Target: "slow-echo",
				Input:  map[string]any{"prompt": fmt.Sprintf("conc-%d", i)},
			}, sink)
			cancel()
			if err != nil {
				errCh <- fmt.Errorf("concurrent execute %d: %w", i, err)
			}
		}
		done <- struct{}{}
	}()

	go func() {
		time.Sleep(200 * time.Millisecond)
		_ = c.Stop(ctx)
		done <- struct{}{}
	}()

	go func() {
		time.Sleep(300 * time.Millisecond)
		for i := 0; i < 2; i++ {
			sink := &testutil.FakeSink{}
			execCtx, cancel := context.WithTimeout(ctx, 200*time.Millisecond)
			err := c.Execute(execCtx, noderuntime.ExecutionSpec{
				RunID:  fmt.Sprintf("run-post-stop-%d", i),
				Target: "slow-echo",
				Input:  map[string]any{"prompt": fmt.Sprintf("post-stop-%d", i)},
			}, sink)
			cancel()
			if err != nil {
				errCh <- fmt.Errorf("post-stop execute %d: %w", i, err)
			}
		}
		done <- struct{}{}
	}()

	timeout := time.After(10 * time.Second)
	for completed := 0; completed < 3; completed++ {
		select {
		case <-done:
		case <-timeout:
			t.Fatal("TestCLIConcurrentExecuteAndStop timed out; possible deadlock")
		}
	}
	close(errCh)
	for range errCh {
	}
}

func TestCLIStartPartialRollbackWithMarkers(t *testing.T) {
	testutil.RequireUnixShell(t)

	markerDir := t.TempDir()
	startMarker := "START_MARKER_A"
	startMarkerPath := filepath.Join(markerDir, "marker_a")
	profileACmd := fmt.Sprintf(`mkdir -p %s; echo %s > %s/marker_a; while IFS= read -r line; do printf "reply:%%s\n" "$line"; done`,
		markerDir, startMarker, markerDir)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"profile-a": {
				Command:               "sh",
				Args:                  []string{"-c", profileACmd},
				Persistent:            true,
				Terminal:              true,
				StartupIdleTimeoutMS:  50,
				ResponseIdleTimeoutMS: 200,
			},
			"profile-b": {
				Command:              "sh",
				Args:                 []string{"-c", "exit 2"},
				Persistent:           true,
				Terminal:             true,
				StartupIdleTimeoutMS: 50,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()

	if err := c.Start(ctx); err == nil {
		t.Fatal("expected Start to fail when profile-b exits immediately")
	}

	_ = c.Stop(ctx)
	time.Sleep(300 * time.Millisecond)

	testutil.RequireEventually(t, 2*time.Second, 50*time.Millisecond, func() bool {
		return testutil.ReadMarker(startMarkerPath) == startMarker
	})

	// After rollback, the pre-started default session for profile-a is gone.
	sink := &testutil.FakeSink{}
	if err := c.Execute(ctx, noderuntime.ExecutionSpec{
		RunID:       "post-rollback",
		Target:      "profile-a",
		SessionMode: noderuntime.SessionModeRequireExisting,
		Input:       map[string]any{"prompt": "test"},
	}, sink); err == nil {
		t.Fatal("expected Execute for profile-a to fail with no-session after rollback (require-existing)")
	}
}

func TestCLITerminateSessionStopsOnlyTargetSession(t *testing.T) {
	testutil.RequireUnixShell(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"echo-term": {
				Command:               "sh",
				Args:                  []string{"-c", `while IFS= read -r line; do printf "reply:%s\n" "$line"; done`},
				Persistent:            true,
				Terminal:              false,
				ResponseIdleTimeoutMS: 200,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()

	// Create session-a and session-b via lazy creation.
	for _, sid := range []string{"session-a", "session-b"} {
		sink := &testutil.FakeSink{}
		err := c.Execute(ctx, noderuntime.ExecutionSpec{
			RunID:     "run-" + sid,
			Target:    "echo-term",
			SessionID: sid,
			Input:     map[string]any{"prompt": "ping"},
		}, sink)
		if err != nil {
			t.Fatalf("create %s: %v", sid, err)
		}
	}

	// Terminate session-a only.
	if err := c.TerminateSession(ctx, "echo-term", "session-a"); err != nil {
		t.Fatalf("TerminateSession: %v", err)
	}

	// session-b must still respond.
	sink := &testutil.FakeSink{}
	err := c.Execute(ctx, noderuntime.ExecutionSpec{
		RunID:     "run-b-after",
		Target:    "echo-term",
		SessionID: "session-b",
		Input:     map[string]any{"prompt": "pong"},
	}, sink)
	if err != nil {
		t.Fatalf("session-b should still be alive: %v", err)
	}

	// session-a must be gone (require-existing fails).
	sinkA := &testutil.FakeSink{}
	err = c.Execute(ctx, noderuntime.ExecutionSpec{
		RunID:       "run-a-after",
		Target:      "echo-term",
		SessionID:   "session-a",
		SessionMode: noderuntime.SessionModeRequireExisting,
		Input:       map[string]any{"prompt": "should-fail"},
	}, sinkA)
	if err == nil {
		t.Fatal("expected error for terminated session-a with require-existing mode")
	}

	_ = c.Stop(ctx)
}

func TestCLISameSessionDifferentWorkspaceIsolated(t *testing.T) {
	testutil.RequireUnixShell(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"pwd-echo": {
				Command:               "sh",
				Args:                  []string{"-c", `while IFS= read -r line; do pwd; done`},
				Persistent:            true,
				Terminal:              false,
				ResponseIdleTimeoutMS: 200,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()
	defer func() { _ = c.Stop(ctx) }()

	wsA := t.TempDir()
	wsB := t.TempDir()

	runIn := func(ws string) string {
		sink := &testutil.FakeSink{}
		if err := c.Execute(ctx, noderuntime.ExecutionSpec{
			RunID:     "run-" + ws,
			Target:    "pwd-echo",
			SessionID: "shared",
			Workspace: ws,
			Input:     map[string]any{"prompt": "go"},
		}, sink); err != nil {
			t.Fatalf("execute in %q: %v", ws, err)
		}
		return testutil.CollectDeltas(sink.Events())
	}

	outA := runIn(wsA)
	outB := runIn(wsB)

	if !strings.Contains(outA, wsA) {
		t.Errorf("session for workspace A should run in %q, got %q", wsA, outA)
	}
	if !strings.Contains(outB, wsB) {
		t.Errorf("session for workspace B should run in %q, got %q", wsB, outB)
	}
	// Workspace A's session must not have run in workspace B's directory.
	if strings.Contains(outA, wsB) {
		t.Errorf("workspace A session leaked into workspace B dir %q: %q", wsB, outA)
	}

	// Both workspace variants of the shared session must be present and distinct.
	resp, err := c.HandleCommand(ctx, noderuntime.CommandRequest{Type: noderuntime.CommandTypeSessionList})
	if err != nil {
		t.Fatalf("session list: %v", err)
	}
	if got := resp.Result["count"]; got != "2" {
		t.Fatalf("expected 2 isolated sessions, count = %q", got)
	}
}

func TestCLITerminateSessionStopsAllWorkspaceVariants(t *testing.T) {
	testutil.RequireUnixShell(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"echo-ws": {
				Command:               "sh",
				Args:                  []string{"-c", `while IFS= read -r line; do printf "reply:%s\n" "$line"; done`},
				Persistent:            true,
				Terminal:              false,
				ResponseIdleTimeoutMS: 200,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()
	defer func() { _ = c.Stop(ctx) }()

	wsA := t.TempDir()
	wsB := t.TempDir()

	// Same target/sessionID across two workspaces.
	for _, ws := range []string{wsA, wsB} {
		sink := &testutil.FakeSink{}
		if err := c.Execute(ctx, noderuntime.ExecutionSpec{
			RunID:     "run-create-" + ws,
			Target:    "echo-ws",
			SessionID: "shared",
			Workspace: ws,
			Input:     map[string]any{"prompt": "ping"},
		}, sink); err != nil {
			t.Fatalf("create session in %q: %v", ws, err)
		}
	}

	// The workspace-less terminate command must close every variant.
	if err := c.TerminateSession(ctx, "echo-ws", "shared"); err != nil {
		t.Fatalf("TerminateSession: %v", err)
	}

	// Both workspace variants must now be gone (require-existing fails).
	for _, ws := range []string{wsA, wsB} {
		sink := &testutil.FakeSink{}
		err := c.Execute(ctx, noderuntime.ExecutionSpec{
			RunID:       "run-after-" + ws,
			Target:      "echo-ws",
			SessionID:   "shared",
			Workspace:   ws,
			SessionMode: noderuntime.SessionModeRequireExisting,
			Input:       map[string]any{"prompt": "should-fail"},
		}, sink)
		if err == nil {
			t.Fatalf("workspace %q variant should be terminated, but require-existing succeeded", ws)
		}
	}
}

func TestCLIStopStopsAllLogicalSessions(t *testing.T) {
	testutil.RequireUnixShell(t)

	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"echo-stop": {
				Command:               "sh",
				Args:                  []string{"-c", `while IFS= read -r line; do printf "reply:%s\n" "$line"; done`},
				Persistent:            true,
				Terminal:              false,
				ResponseIdleTimeoutMS: 200,
			},
		},
	}
	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()

	// Create three logical sessions.
	for _, sid := range []string{"s1", "s2", "s3"} {
		sink := &testutil.FakeSink{}
		if err := c.Execute(ctx, noderuntime.ExecutionSpec{
			RunID:     "run-" + sid,
			Target:    "echo-stop",
			SessionID: sid,
			Input:     map[string]any{"prompt": "ping"},
		}, sink); err != nil {
			t.Fatalf("create %s: %v", sid, err)
		}
	}

	if err := c.Stop(ctx); err != nil {
		t.Fatalf("Stop: %v", err)
	}

	// After Stop, all sessions must be gone (require-existing must fail).
	for _, sid := range []string{"s1", "s2", "s3"} {
		sink := &testutil.FakeSink{}
		err := c.Execute(ctx, noderuntime.ExecutionSpec{
			RunID:       "run-after-" + sid,
			Target:      "echo-stop",
			SessionID:   sid,
			SessionMode: noderuntime.SessionModeRequireExisting,
			Input:       map[string]any{"prompt": "should-fail"},
		}, sink)
		if err == nil {
			t.Fatalf("session %q should be stopped after Stop()", sid)
		}
	}
}

func TestCLIHandleCommandUsageStatusUsesSelectedAgent(t *testing.T) {
	c := clipkg.New(config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"codex":    {Command: "/tmp/fake-codex"},
			"cline-m1": {Command: "cline-m1"},
		},
	}, zap.NewNop())

	c.StatusChecker = func(ctx context.Context, target string, profile config.CLIProfileConf) (*status.UsageStatus, error) {
		if target == "codex" {
			if profile.Command != "/tmp/fake-codex" {
				t.Errorf("expected command /tmp/fake-codex, got %q", profile.Command)
			}
			return &status.UsageStatus{RawOutput: "fake-codex-status"}, nil
		}
		return nil, nil
	}

	_, err := c.HandleCommand(context.Background(), noderuntime.CommandRequest{
		Type:   noderuntime.CommandTypeUsageStatus,
		Target: "unknown",
	})
	if err == nil || !strings.Contains(err.Error(), "unknown target") {
		t.Errorf("expected unknown target error, got %v", err)
	}

	resp, err := c.HandleCommand(context.Background(), noderuntime.CommandRequest{
		RequestID: "req-123",
		Type:      noderuntime.CommandTypeUsageStatus,
		Target:    "codex",
		SessionID: "sess-456",
		Adapter:   "cli",
	})
	if err != nil {
		t.Fatalf("HandleCommand failed: %v", err)
	}
	if resp.UsageStatus == nil || resp.UsageStatus.RawOutput != "fake-codex-status" {
		t.Errorf("unexpected usage status: %+v", resp.UsageStatus)
	}
	if resp.RequestID != "req-123" {
		t.Errorf("expected RequestID req-123, got %s", resp.RequestID)
	}
	if resp.SessionID != "sess-456" {
		t.Errorf("expected SessionID sess-456, got %s", resp.SessionID)
	}

	if meta := resp.UsageStatus.Metadata; meta == nil || meta["parse_status"] != "raw_only" {
		t.Errorf("expected parse_status=raw_only metadata, got %+v", meta)
	}

	_, err = c.HandleCommand(context.Background(), noderuntime.CommandRequest{
		Type:   noderuntime.CommandType("invalid"),
		Target: "codex",
	})
	if err == nil || !strings.Contains(err.Error(), "unsupported command") {
		t.Errorf("expected unsupported command error, got %v", err)
	}
}

func TestCLIHandleCommandUsageStatusMetadataOnly(t *testing.T) {
	c := clipkg.New(config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"codex": {Command: "/tmp/fake-codex"},
		},
	}, zap.NewNop())

	c.StatusChecker = func(_ context.Context, _ string, _ config.CLIProfileConf) (*status.UsageStatus, error) {
		return &status.UsageStatus{
			Metadata: map[string]string{"custom_key": "custom_value"},
		}, nil
	}

	resp, err := c.HandleCommand(context.Background(), noderuntime.CommandRequest{
		Type:   noderuntime.CommandTypeUsageStatus,
		Target: "codex",
	})
	if err != nil {
		t.Fatalf("HandleCommand: %v", err)
	}
	if resp.UsageStatus == nil {
		t.Fatal("expected UsageStatus, got nil")
	}
	if got, ok := resp.UsageStatus.Metadata["parse_status"]; ok {
		t.Errorf("metadata-only status must not have parse_status annotation, got %q", got)
	}
	if got := resp.UsageStatus.Metadata["custom_key"]; got != "custom_value" {
		t.Errorf("custom_key: got %q want %q", got, "custom_value")
	}
}

func TestCLIHandleCommandUsageStatusEmptyFallback(t *testing.T) {
	c := clipkg.New(config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"codex": {Command: "/tmp/fake-codex"},
		},
	}, zap.NewNop())

	c.StatusChecker = func(_ context.Context, _ string, _ config.CLIProfileConf) (*status.UsageStatus, error) {
		return &status.UsageStatus{}, nil
	}

	resp, err := c.HandleCommand(context.Background(), noderuntime.CommandRequest{
		Type:   noderuntime.CommandTypeUsageStatus,
		Target: "codex",
	})
	if err != nil {
		t.Fatalf("HandleCommand: %v", err)
	}
	if resp.UsageStatus == nil {
		t.Fatal("expected UsageStatus, got nil")
	}
	if meta := resp.UsageStatus.Metadata; meta == nil || meta["parse_status"] != "empty" {
		t.Errorf("expected parse_status=empty for truly empty status, got %+v", meta)
	}
}

func TestCLIHandleCommandUsageStatusNilCheckerResult(t *testing.T) {
	c := clipkg.New(config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"codex": {Command: "/tmp/fake-codex"},
		},
	}, zap.NewNop())

	c.StatusChecker = func(_ context.Context, _ string, _ config.CLIProfileConf) (*status.UsageStatus, error) {
		return nil, nil
	}

	_, err := c.HandleCommand(context.Background(), noderuntime.CommandRequest{
		Type:   noderuntime.CommandTypeUsageStatus,
		Target: "codex",
	})
	if err == nil || !strings.Contains(err.Error(), "nil result") {
		t.Fatalf("expected nil result error, got %v", err)
	}
}

func TestCLIHandleCommandUsageStatusRawOnlyMetadata(t *testing.T) {
	c := clipkg.New(config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"codex": {Command: "/tmp/fake-codex"},
		},
	}, zap.NewNop())

	c.StatusChecker = func(_ context.Context, _ string, _ config.CLIProfileConf) (*status.UsageStatus, error) {
		return &status.UsageStatus{RawOutput: "some raw usage output"}, nil
	}

	resp, err := c.HandleCommand(context.Background(), noderuntime.CommandRequest{
		RequestID: "req-raw",
		Type:      noderuntime.CommandTypeUsageStatus,
		Target:    "codex",
	})
	if err != nil {
		t.Fatalf("HandleCommand: %v", err)
	}
	if resp.UsageStatus == nil {
		t.Fatal("expected UsageStatus, got nil")
	}
	if resp.UsageStatus.RawOutput != "some raw usage output" {
		t.Errorf("RawOutput: got %q want %q", resp.UsageStatus.RawOutput, "some raw usage output")
	}
	if meta := resp.UsageStatus.Metadata; meta == nil || meta["parse_status"] != "raw_only" {
		t.Errorf("expected parse_status=raw_only, got %+v", meta)
	}
}

func TestCLIHandleCommandSessionListReturnsEmptyResult(t *testing.T) {
	c := clipkg.New(config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"codex": {Command: "/tmp/fake-codex"},
		},
	}, zap.NewNop())

	resp, err := c.HandleCommand(context.Background(), noderuntime.CommandRequest{
		RequestID: "req-list",
		Type:      noderuntime.CommandTypeSessionList,
		Adapter:   "cli",
	})
	if err != nil {
		t.Fatalf("HandleCommand: %v", err)
	}
	if resp.Result == nil {
		t.Fatalf("expected result map, got nil")
	}
	if got := resp.Result["count"]; got != "0" {
		t.Fatalf("count: got %q want %q", got, "0")
	}
	if got, ok := resp.Result["sessions"]; !ok || got != "" {
		t.Fatalf("sessions: got %q present=%v want empty string", got, ok)
	}
}

func TestCapabilities_OnlyConfiguredProfiles(t *testing.T) {
	c := clipkg.New(config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"foo": {Command: "foo"},
			"bar": {Command: "bar"},
		},
	}, zap.NewNop())

	caps, err := c.Capabilities(context.Background())
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if caps.MaxConcurrency != 0 {
		t.Fatalf("expected unlimited MaxConcurrency 0, got %d", caps.MaxConcurrency)
	}
	want := []string{"bar", "foo"}
	if len(caps.Targets) != len(want) {
		t.Fatalf("expected models %v, got %v", want, caps.Targets)
	}
	for i, m := range want {
		if caps.Targets[i] != m {
			t.Errorf("Models[%d] = %q, want %q", i, caps.Targets[i], m)
		}
	}
}

func TestCapabilities_EmptyProfilesReturnsEmptyModels(t *testing.T) {
	c := clipkg.New(config.CLIConf{
		Enabled:  true,
		Profiles: map[string]config.CLIProfileConf{},
	}, zap.NewNop())

	caps, err := c.Capabilities(context.Background())
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if len(caps.Targets) != 0 {
		t.Errorf("expected empty models, got %v", caps.Targets)
	}
}
