package claudecode

import (
	"strings"
	"testing"
)

// TestRenderPrompt_OutputContractWithoutChannel pins the baseline:
// without a sidecar channel, the rendered prompt instructs the model
// to emit a fenced harness-out block and says nothing about a side
// channel. This is the long-standing TUI-scrape behavior — must not
// regress.
func TestRenderPrompt_OutputContractWithoutChannel(t *testing.T) {
	payload := `{"prompt":"hello world","available_tools":["delegate"]}`
	got := renderPrompt(payload, "")
	if !strings.Contains(got, "Respond ONLY with a fenced `harness-out` block") {
		t.Errorf("baseline output-contract text missing:\n%s", got)
	}
	if strings.Contains(got, "Side channel") {
		t.Errorf("side-channel section present without an instruction:\n%s", got)
	}
}

// TestRenderPrompt_FoldsInChannelInstruction proves the wiring from
// SidecarChannel.Open → adapter.ChannelInstruction → renderPrompt.
func TestRenderPrompt_FoldsInChannelInstruction(t *testing.T) {
	payload := `{"prompt":"hello"}`
	instr := "To finish a turn, run `harness-send '<JSON>'`. Socket: /tmp/abc.sock."
	got := renderPrompt(payload, instr)

	if !strings.Contains(got, instr) {
		t.Errorf("rendered prompt missing channel instruction\nwant substring: %q\nrendered:\n%s", instr, got)
	}
	if !strings.Contains(got, "Side channel") {
		t.Errorf("rendered prompt missing Side-channel header:\n%s", got)
	}
	if !strings.Contains(got, "```harness-out") {
		t.Errorf("rendered prompt dropped the fenced-block fallback:\n%s", got)
	}
}

// TestRenderPrompt_MailboxInstructionIsRendered confirms the renderer
// is channel-agnostic — it embeds whatever Instruction the channel
// returned, regardless of socket vs mailbox.
func TestRenderPrompt_MailboxInstructionIsRendered(t *testing.T) {
	payload := `{"prompt":"hi"}`
	instr := "Write your JSON to /run/agents/x/outbox/outbox.json via the Write tool."
	got := renderPrompt(payload, instr)
	if !strings.Contains(got, "/run/agents/x/outbox/outbox.json") {
		t.Errorf("mailbox path missing in rendered prompt:\n%s", got)
	}
	if !strings.Contains(got, "Write tool") {
		t.Errorf("Write-tool instruction missing:\n%s", got)
	}
}

// TestPaneAdapter_SendThreadsChannelInstruction proves the adapter's
// ChannelInstruction field reaches renderPrompt (same code path as
// PaneAdapter.Send, which is just renderPrompt + Pane.Send).
func TestPaneAdapter_SendThreadsChannelInstruction(t *testing.T) {
	a := &PaneAdapter{ChannelInstruction: "USE-CHANNEL-XYZ"}
	rendered := renderPrompt(`{"prompt":"x"}`, a.ChannelInstruction)
	if !strings.Contains(rendered, "USE-CHANNEL-XYZ") {
		t.Errorf("ChannelInstruction not threaded into render output:\n%s", rendered)
	}
}
