package helpers

import (
	"encoding/json"

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

// TextBlock creates a text content block.
func TextBlock(text string) schema.ContentBlock {
	return schema.ContentBlock{
		Type: schema.TypeContentBlockKindText,
		Text: &schema.TextContent{Text: text},
	}
}

// ImageBlock creates an image content block.
func ImageBlock(data, mimeType string) schema.ContentBlock {
	return schema.ContentBlock{
		Type:  schema.TypeContentBlockKindImage,
		Image: &schema.ImageContent{Data: data, MimeType: mimeType},
	}
}

// AudioBlock creates an audio content block.
func AudioBlock(data, mimeType string) schema.ContentBlock {
	return schema.ContentBlock{
		Type:  schema.TypeContentBlockKindAudio,
		Audio: &schema.AudioContent{Data: data, MimeType: mimeType},
	}
}

// ResourceLinkBlock creates a resource link content block.
func ResourceLinkBlock(name, uri string) schema.ContentBlock {
	return schema.ContentBlock{
		Type:          schema.TypeContentBlockKindResource_link,
		Resource_link: &schema.ResourceLink{Name: name, Uri: uri},
	}
}

// EmbeddedTextResource creates an embedded text resource content block.
func EmbeddedTextResource(uri, text string) schema.ContentBlock {
	return schema.ContentBlock{
		Type: schema.TypeContentBlockKindResource,
		Resource: &schema.EmbeddedResource{
			Resource: &schema.EmbeddedResourceResource{
				Type:                 schema.TypeEmbeddedResourceResourceKindTextResourceContents,
				TextResourceContents: &schema.TextResourceContents{Uri: uri, MimeType: ptrString("text/plain"), Text: text},
			},
		},
	}
}

// EmbeddedBlobResource creates an embedded blob resource content block.
func EmbeddedBlobResource(uri, blob, mimeType string) schema.ContentBlock {
	return schema.ContentBlock{
		Type: schema.TypeContentBlockKindResource,
		Resource: &schema.EmbeddedResource{
			Resource: &schema.EmbeddedResourceResource{
				Type:                 schema.TypeEmbeddedResourceResourceKindBlobResourceContents,
				BlobResourceContents: &schema.BlobResourceContents{Uri: uri, MimeType: ptrString(mimeType), Blob: blob},
			},
		},
	}
}

// AgentMessageUpdate creates a session update for an agent message chunk.
func AgentMessageUpdate(text string) schema.SessionUpdate {
	return schema.SessionUpdate{
		SessionUpdate:     schema.SessionUpdateKindAgentMessageChunk,
		AgentMessageChunk: &schema.ContentChunk{Content: &schema.ContentBlock{Type: schema.TypeContentBlockKindText, Text: &schema.TextContent{Text: text}}},
	}
}

// AgentThoughtUpdate creates a session update for an agent thought chunk.
func AgentThoughtUpdate(text string) schema.SessionUpdate {
	return schema.SessionUpdate{
		SessionUpdate:     schema.SessionUpdateKindAgentThoughtChunk,
		AgentThoughtChunk: &schema.ContentChunk{Content: &schema.ContentBlock{Type: schema.TypeContentBlockKindText, Text: &schema.TextContent{Text: text}}},
	}
}

// ToolCallStartUpdate creates a session update for starting a tool call.
func ToolCallStartUpdate(tc schema.ToolCall) schema.SessionUpdate {
	return schema.SessionUpdate{
		SessionUpdate: schema.SessionUpdateKindToolCall,
		ToolCall:      &tc,
	}
}

// ToolCallProgressUpdate creates a session update for tool call progress.
func ToolCallProgressUpdate(update schema.ToolCallUpdate) schema.SessionUpdate {
	return schema.SessionUpdate{
		SessionUpdate:  schema.SessionUpdateKindToolCallUpdate,
		ToolCallUpdate: &update,
	}
}

// PlanUpdate creates a session update for a plan.
func PlanUpdate(entries []*schema.PlanEntry) schema.SessionUpdate {
	return schema.SessionUpdate{
		SessionUpdate: schema.SessionUpdateKindPlan,
		Plan:          &schema.Plan{Entries: entries},
	}
}

// PlanEntry creates a plan entry with the given content, priority and status.
func PlanEntry(content string, priority schema.PlanEntryPriority, status schema.PlanEntryStatus) schema.PlanEntry {
	return schema.PlanEntry{Content: content, Priority: &priority, Status: &status}
}

// SessionNotification wraps a session update into a notification.
func SessionNotification(sessionID string, update schema.SessionUpdate) *schema.SessionNotification {
	return &schema.SessionNotification{
		SessionId: ptrSessionId(sessionID),
		Update:    &update,
	}
}

// DefaultPermissionOptions returns the standard set of permission options.
func DefaultPermissionOptions() []*schema.PermissionOption {
	return []*schema.PermissionOption{
		{OptionId: ptrOptId("allow_once"), Name: "Allow once", Kind: ptrKind(schema.PermissionOptionKindAllowOnce)},
		{OptionId: ptrOptId("allow_always"), Name: "Allow always", Kind: ptrKind(schema.PermissionOptionKindAllowAlways)},
		{OptionId: ptrOptId("reject_once"), Name: "Reject", Kind: ptrKind(schema.PermissionOptionKindRejectOnce)},
	}
}

func ptrString(s string) *string                                         { return &s }
func ptrSessionId(s string) *schema.SessionId                            { v := schema.SessionId(s); return &v }
func ptrOptId(s string) *schema.PermissionOptionId                       { v := schema.PermissionOptionId(s); return &v }
func ptrKind(k schema.PermissionOptionKind) *schema.PermissionOptionKind { return &k }

// StartReadToolCall creates a tool call for reading a file, with pending status.
func StartReadToolCall(id, title, path string) schema.ToolCall {
	return schema.ToolCall{
		ToolCallId: ptrTcId(id),
		Title:      title,
		Kind:       ptrToolKind(schema.ToolKindRead),
		Status:     ptrStatus(schema.ToolCallStatusPending),
		RawInput:   mustMarshal(map[string]any{"path": path}),
	}
}

// StartEditToolCall creates a tool call for editing a file, with pending status.
func StartEditToolCall(id, title, path, newText string) schema.ToolCall {
	return schema.ToolCall{
		ToolCallId: ptrTcId(id),
		Title:      title,
		Kind:       ptrToolKind(schema.ToolKindEdit),
		Status:     ptrStatus(schema.ToolCallStatusPending),
		RawInput:   mustMarshal(map[string]any{"path": path, "newText": newText}),
	}
}

// StartTerminalToolCall creates a tool call for a terminal session, with pending status.
func StartTerminalToolCall(id, title, terminalID string) schema.ToolCall {
	return schema.ToolCall{
		ToolCallId: ptrTcId(id),
		Title:      title,
		Kind:       ptrToolKind(schema.ToolKindExecute),
		Status:     ptrStatus(schema.ToolCallStatusPending),
		RawInput:   mustMarshal(map[string]any{"terminalId": terminalID}),
	}
}

// UpdateToolCallResult updates a tool call to completed status with the given content.
func UpdateToolCallResult(tc *schema.ToolCall, content string) {
	tc.Status = ptrStatus(schema.ToolCallStatusCompleted)
	tc.Content = append(tc.Content, &schema.ToolCallContent{
		Type:    schema.TypeToolCallContentKindContent,
		Content: &schema.Content{Content: &schema.ContentBlock{Type: schema.TypeContentBlockKindText, Text: &schema.TextContent{Text: content}}},
	})
}

func ptrStatus(s schema.ToolCallStatus) *schema.ToolCallStatus { return &s }
func ptrTcId(s string) *schema.ToolCallId                      { v := schema.ToolCallId(s); return &v }
func ptrToolKind(k schema.ToolKind) *schema.ToolKind           { return &k }

func mustMarshal(v any) json.RawMessage {
	data, err := json.Marshal(v)
	if err != nil {
		return nil
	}
	return data
}
