package helpers

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/keepmind9/acp-sdk-go/schema"
)

func TestTextBlock(t *testing.T) {
	block := TextBlock("hello")
	assert.Equal(t, schema.TypeContentBlockKindText, block.Type)
	require.NotNil(t, block.Text)
	assert.Equal(t, "hello", block.Text.Text)
}

func TestImageBlock(t *testing.T) {
	block := ImageBlock("base64data", "image/png")
	assert.Equal(t, schema.TypeContentBlockKindImage, block.Type)
	require.NotNil(t, block.Image)
	assert.Equal(t, "base64data", block.Image.Data)
}

func TestAudioBlock(t *testing.T) {
	block := AudioBlock("base64audio", "audio/wav")
	assert.Equal(t, schema.TypeContentBlockKindAudio, block.Type)
	require.NotNil(t, block.Audio)
	assert.Equal(t, "base64audio", block.Audio.Data)
}

func TestAgentMessageUpdate(t *testing.T) {
	update := AgentMessageUpdate("hello world")
	assert.Equal(t, schema.SessionUpdateKindAgentMessageChunk, update.SessionUpdate)
	require.NotNil(t, update.AgentMessageChunk)
	require.NotNil(t, update.AgentMessageChunk.Content)
	assert.Equal(t, "hello world", update.AgentMessageChunk.Content.Text.Text)
}

func TestAgentThoughtUpdate(t *testing.T) {
	update := AgentThoughtUpdate("thinking...")
	assert.Equal(t, schema.SessionUpdateKindAgentThoughtChunk, update.SessionUpdate)
	require.NotNil(t, update.AgentThoughtChunk)
}

func TestPlanUpdate(t *testing.T) {
	high := schema.PlanEntryPriorityHigh
	medium := schema.PlanEntryPriorityMedium
	inProgress := schema.PlanEntryStatusInProgress
	pending := schema.PlanEntryStatusPending
	entries := []*schema.PlanEntry{
		{Content: "step 1", Priority: &high, Status: &inProgress},
		{Content: "step 2", Priority: &medium, Status: &pending},
	}
	update := PlanUpdate(entries)
	assert.Equal(t, schema.SessionUpdateKindPlan, update.SessionUpdate)
	require.NotNil(t, update.Plan)
	require.Len(t, update.Plan.Entries, 2)
	assert.Equal(t, "step 1", update.Plan.Entries[0].Content)
}

func TestPlanEntryHelper(t *testing.T) {
	high := schema.PlanEntryPriorityHigh
	pending := schema.PlanEntryStatusPending
	entry := PlanEntry("do thing", high, pending)
	assert.Equal(t, "do thing", entry.Content)
	require.NotNil(t, entry.Priority)
	assert.Equal(t, high, *entry.Priority)
	require.NotNil(t, entry.Status)
	assert.Equal(t, pending, *entry.Status)
}

func TestSessionNotification(t *testing.T) {
	notif := SessionNotification("sess-1", AgentMessageUpdate("hello"))
	require.NotNil(t, notif.SessionId)
	assert.Equal(t, "sess-1", *notif.SessionId)
	assert.Equal(t, schema.SessionUpdateKindAgentMessageChunk, notif.Update.SessionUpdate)
}

func TestDefaultPermissionOptions(t *testing.T) {
	opts := DefaultPermissionOptions()
	require.Len(t, opts, 3)
	require.NotNil(t, opts[0].Kind)
	assert.Equal(t, schema.PermissionOptionKindAllowOnce, *opts[0].Kind)
	require.NotNil(t, opts[1].Kind)
	assert.Equal(t, schema.PermissionOptionKindAllowAlways, *opts[1].Kind)
	require.NotNil(t, opts[2].Kind)
	assert.Equal(t, schema.PermissionOptionKindRejectOnce, *opts[2].Kind)
}

func TestToolCallStartUpdate(t *testing.T) {
	tcid := schema.ToolCallId("tc-1")
	tc := schema.ToolCall{
		ToolCallId: &tcid,
		Title:      "read file",
	}
	update := ToolCallStartUpdate(tc)
	assert.Equal(t, schema.SessionUpdateKindToolCall, update.SessionUpdate)
	require.NotNil(t, update.ToolCall)
	require.NotNil(t, update.ToolCall.ToolCallId)
	assert.Equal(t, "tc-1", *update.ToolCall.ToolCallId)
}

func TestHelpersJSONRoundtrip(t *testing.T) {
	block := TextBlock("test")
	data, err := json.Marshal(block)
	require.NoError(t, err)

	var decoded map[string]any
	require.NoError(t, json.Unmarshal(data, &decoded))
	assert.Equal(t, "text", decoded["type"])
}
