package promptcompiler

import "strings"

func promptMapValue(values map[string]any, key string) map[string]any {
	raw, _ := values[key].(map[string]any)
	return raw
}

func promptActorLabel(raw map[string]any) string {
	for _, key := range []string{"name", "targetId", "serviceSlug", "displayName", "principalId", "memberId", "id"} {
		if name := promptStringMapValue(raw, key); name != "" {
			if !strings.HasPrefix(name, "@") {
				return "@" + name
			}
			return name
		}
	}
	return ""
}

// TaskPromptActor is the normalized actor projection used by task templates.
type TaskPromptActor struct {
	Label string
}

// TaskPromptDiscussion is the normalized task discussion projection.
type TaskPromptDiscussion struct {
	Body  string
	Actor string
}

// TaskPromptRecord is the typed task projection consumed by prompt rendering.
type TaskPromptRecord struct {
	TaskNumber         int64
	HasTaskNumber      bool
	Title              string
	TaskScope          string
	RootTaskNumber     int64
	ParentTaskNumber   int64
	ChannelRef         string
	Status             string
	Kind               string
	Priority           string
	BlockedReason      string
	Assignee           string
	Description        string
	AcceptanceCriteria []string
	ReviewChecklist    []string
	PinnedMessageRefs  []string
	RelevantURLs       []string
	WorkspaceRefs      []string
}

// TaskPromptMetadata is the typed boundary between Inbox metadata and prompt
// rendering. JSON-shaped metadata is decoded once here; text_task.go never
// interprets map[string]any values.
type TaskPromptMetadata struct {
	MessageType string
	Task        TaskPromptRecord
	HasTask     bool
	Discussion  *TaskPromptDiscussion
}

type TaskPromptAttribute struct {
	Label string
	Value string
}

type TaskPromptChecklist struct {
	Label string
	Items []string
}

// TaskPromptTemplateData is the template-facing task projection. Labels,
// checklist layout, and discussion branches live in the registered template.
type TaskPromptDetailsTemplateData struct {
	Status             string
	Kind               string
	Priority           string
	BlockedReason      string
	Assignee           string
	Description        string
	AcceptanceCriteria []string
	ReviewChecklist    []string
	PinnedMessageRefs  []string
	RelevantURLs       []string
	WorkspaceRefs      []string
}

type TaskPromptTemplateData struct {
	Discussion    bool
	Label         string
	TaskNumber    int64
	HasTaskNumber bool
	Title         string
	ChannelRef    string
	Details       TaskPromptDetailsTemplateData
	Attributes    []TaskPromptAttribute
	Checklists    []TaskPromptChecklist
	CommentBy     string
	CommentBody   string
	ReplyTool     string
}

func decodeTaskPromptMetadata(messageType string, metadata map[string]any) (TaskPromptMetadata, bool) {
	if messageType != "task_dispatch" || len(metadata) == 0 {
		return TaskPromptMetadata{}, false
	}
	rawTask, ok := metadata["task"].(map[string]any)
	if !ok || len(rawTask) == 0 {
		return TaskPromptMetadata{}, false
	}
	result := TaskPromptMetadata{
		MessageType: messageType,
		Task:        decodeTaskPromptRecord(rawTask),
		HasTask:     true,
	}
	if rawDiscussion, ok := metadata["taskDiscussion"].(map[string]any); ok {
		createdBy, _ := rawDiscussion["createdBy"].(map[string]any)
		result.Discussion = &TaskPromptDiscussion{Body: promptStringMapValue(rawDiscussion, "body"), Actor: promptActorLabel(createdBy)}
	}
	return result, true
}

func promptIntMapValueDefault(raw map[string]any, key string) int64 {
	value, _ := promptIntMapValue(raw, key)
	return value
}

func decodeTaskPromptRecord(raw map[string]any) TaskPromptRecord {
	taskNumber, hasTaskNumber := promptIntMapValue(raw, "taskNumber")
	return TaskPromptRecord{
		TaskNumber:         taskNumber,
		HasTaskNumber:      hasTaskNumber,
		Title:              promptStringMapValue(raw, "title"),
		TaskScope:          firstNonEmptyPromptAuthorValue(promptStringMapValue(raw, "taskScope"), promptStringMapValue(raw, "taskScopeRef"), promptStringMapValue(raw, "taskScopeTarget"), promptStringMapValue(raw, "taskScopeId")),
		RootTaskNumber:     promptIntMapValueDefault(raw, "rootTaskNumber"),
		ParentTaskNumber:   promptIntMapValueDefault(raw, "parentTaskNumber"),
		ChannelRef:         promptStringMapValue(raw, "channelRef"),
		Status:             promptStringMapValue(raw, "status"),
		Kind:               promptStringMapValue(raw, "kind"),
		Priority:           promptStringMapValue(raw, "priority"),
		BlockedReason:      promptTrimRunes(promptStringMapValue(raw, "blockedReason"), promptTaskChecklistItemRunes),
		Assignee:           promptActorLabel(promptMapValue(raw, "assigneeProfile")),
		Description:        promptTrimRunes(promptStringMapValue(raw, "description"), promptTaskDescriptionMaxRunes),
		AcceptanceCriteria: promptStringSliceMapValue(raw, "acceptanceCriteria"),
		ReviewChecklist:    promptStringSliceMapValue(raw, "reviewChecklist"),
		PinnedMessageRefs:  promptStringSliceMapValue(raw, "pinnedMessageRefs"),
		RelevantURLs:       promptStringSliceMapValue(raw, "relevantURLs"),
		WorkspaceRefs:      promptStringSliceMapValue(raw, "workspaceRefs"),
	}
}
