package cli_test

import (
	"context"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"go.uber.org/zap"

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

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

	agy := writeFakeAgy(t, `#!/usr/bin/env sh
log_file=""
conversation=""
prompt=""

while [ "$#" -gt 0 ]; do
  case "$1" in
    --log-file)
      log_file="$2"
      shift 2
      ;;
    --conversation)
      conversation="$2"
      shift 2
      ;;
    --print-timeout)
      shift 2
      ;;
    --dangerously-skip-permissions|--print)
      shift
      ;;
    *)
      prompt="$1"
      shift
      ;;
  esac
done

if [ -z "$log_file" ]; then
  echo "missing --log-file" >&2
  exit 9
fi

if [ -z "$conversation" ]; then
  printf 'I0000 server.go:747] Created conversation 11111111-2222-3333-4444-555555555555\n' >> "$log_file"
  printf 'reply:first:%s\n' "$prompt"
else
  printf 'I0000 printmode.go:71] Print mode: starting (promptLength=1, model="", conversationID="%s")\n' "$conversation" >> "$log_file"
  printf 'reply:resume:%s:%s\n' "$conversation" "$prompt"
fi
`)
	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"antigravity": {
				Command: agy,
				Args: []string{
					"--dangerously-skip-permissions",
					"--print-timeout",
					"10m",
					"--print",
				},
				Mode: "antigravity-print",
				ResumeArgs: []string{
					"--dangerously-skip-permissions",
					"--print-timeout",
					"10m",
					"--conversation",
				},
			},
		},
	}

	c := clipkg.New(cfg, zap.NewNop())
	ctx := context.Background()

	first := &testutil.FakeSink{}
	if err := c.Execute(ctx, noderuntime.ExecutionSpec{
		RunID:     "run-1",
		Target:    "antigravity",
		SessionID: "session-a",
		Input:     map[string]any{"prompt": "first"},
	}, first); err != nil {
		t.Fatalf("first execute: %v", err)
	}
	if combined := testutil.CollectDeltas(first.Events()); !strings.Contains(combined, "reply:first:first") {
		t.Fatalf("first execute output: %q", combined)
	}

	second := &testutil.FakeSink{}
	if err := c.Execute(ctx, noderuntime.ExecutionSpec{
		RunID:     "run-2",
		Target:    "antigravity",
		SessionID: "session-a",
		Input:     map[string]any{"prompt": "second"},
	}, second); err != nil {
		t.Fatalf("second execute: %v", err)
	}
	if combined := testutil.CollectDeltas(second.Events()); !strings.Contains(combined, "reply:resume:11111111-2222-3333-4444-555555555555:second") {
		t.Fatalf("second execute output: %q", combined)
	}
}

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

	agy := writeFakeAgy(t, `#!/usr/bin/env sh
echo "should not be called when resume_args is missing" >&2
exit 42
`)
	cfg := config.CLIConf{
		Enabled: true,
		Profiles: map[string]config.CLIProfileConf{
			"antigravity": {
				Command:    agy,
				Args:       []string{"--print"},
				Mode:       "antigravity-print",
				ResumeArgs: nil,
			},
		},
	}

	c := clipkg.New(cfg, zap.NewNop())
	err := c.Execute(context.Background(), noderuntime.ExecutionSpec{
		RunID:     "run-1",
		Target:    "antigravity",
		SessionID: "session-a",
		Input:     map[string]any{"prompt": "first"},
	}, &testutil.FakeSink{})
	if err == nil {
		t.Fatalf("expected error due to missing resume_args, got nil")
	}
	if !strings.Contains(err.Error(), "resume_args") {
		t.Fatalf("expected error to mention resume_args, got: %v", err)
	}
}

func writeFakeAgy(t *testing.T, script string) string {
	t.Helper()

	dir := t.TempDir()
	path := filepath.Join(dir, "agy")
	if err := os.WriteFile(path, []byte(script), 0o755); err != nil {
		t.Fatalf("write fake agy: %v", err)
	}
	return path
}
