package newagentexecute

import (
	"fmt"
	"strings"
	"time"

	newagentmodel "github.com/LoveLosita/smartflow/backend/newAgent/model"
	newagentstream "github.com/LoveLosita/smartflow/backend/newAgent/stream"
	"github.com/cloudwego/eino/schema"
)

const (
	planCurrentStepKey   = "current_step"
	planCurrentStepTitle = "当前步骤"
)

func prepareExecuteNodeInput(input ExecuteNodeInput) (*newagentmodel.AgentRuntimeState, *newagentmodel.ConversationContext, *newagentstream.ChunkEmitter, error) {
	if input.RuntimeState == nil {
		return nil, nil, nil, fmt.Errorf("execute node: runtime state 不能为空")
	}
	if input.Client == nil {
		return nil, nil, nil, fmt.Errorf("execute node: execute client 未注入")
	}

	input.RuntimeState.EnsureCommonState()
	if input.ConversationContext == nil {
		input.ConversationContext = newagentmodel.NewConversationContext("")
	}
	if input.ChunkEmitter == nil {
		input.ChunkEmitter = newagentstream.NewChunkEmitter(newagentstream.NoopPayloadEmitter(), "", "", time.Now().Unix())
	}
	return input.RuntimeState, input.ConversationContext, input.ChunkEmitter, nil
}

func syncExecutePinnedContext(
	conversationContext *newagentmodel.ConversationContext,
	flowState *newagentmodel.CommonState,
) {
	if conversationContext == nil || flowState == nil {
		return
	}

	execContent := buildExecuteContextPinnedMarkdown(flowState)
	if strings.TrimSpace(execContent) != "" {
		conversationContext.UpsertPinnedBlock(newagentmodel.ContextBlock{
			Key:     executePinnedKey,
			Title:   "执行上下文",
			Content: execContent,
		})
	}

	if !flowState.HasPlan() {
		conversationContext.RemovePinnedBlock(planCurrentStepKey)
		return
	}

	step, ok := flowState.CurrentPlanStep()
	if !ok {
		conversationContext.RemovePinnedBlock(planCurrentStepKey)
		return
	}

	current, total := flowState.PlanProgress()
	title := strings.TrimSpace(planCurrentStepTitle)
	if title == "" {
		title = "当前步骤"
	}
	conversationContext.UpsertPinnedBlock(newagentmodel.ContextBlock{
		Key:     planCurrentStepKey,
		Title:   title,
		Content: buildCurrentPlanStepPinnedMarkdown(step, current, total),
	})
}

func appendExecuteStepAdvancedMarker(conversationContext *newagentmodel.ConversationContext) {
	if conversationContext == nil {
		return
	}

	history := conversationContext.HistorySnapshot()
	if len(history) > 0 {
		last := history[len(history)-1]
		if last != nil && last.Extra != nil {
			if kind, ok := last.Extra[executeHistoryKindKey].(string); ok && strings.TrimSpace(kind) == executeHistoryKindStepAdvanced {
				return
			}
		}
	}

	conversationContext.AppendHistory(&schema.Message{
		Role:    schema.Assistant,
		Content: "",
		Extra: map[string]any{
			executeHistoryKindKey: executeHistoryKindStepAdvanced,
		},
	})
}

func buildExecuteContextPinnedMarkdown(flowState *newagentmodel.CommonState) string {
	if flowState == nil {
		return ""
	}

	lines := make([]string, 0, 8)
	if flowState.HasPlan() {
		lines = append(lines, "执行模式：计划执行（按步骤推进）")
		current, total := flowState.PlanProgress()
		lines = append(lines, fmt.Sprintf("计划进度：第 %d/%d 步", current, total))

		if step, ok := flowState.CurrentPlanStep(); ok {
			lines = append(lines, "当前步骤："+compactExecutePinnedText(step.Content))
			doneWhen := compactExecutePinnedText(step.DoneWhen)
			if doneWhen != "" {
				lines = append(lines, "完成判定(done_when)："+doneWhen)
			}
			lines = append(lines, "动作纪律：未满足 done_when 禁止 next_plan；满足后优先 next_plan。")
		} else {
			lines = append(lines, "当前步骤：不可读（可能已执行完成）")
		}
	} else {
		lines = append(lines, "执行模式：自由执行（无预定义步骤）")
	}

	if flowState.MaxRounds > 0 {
		lines = append(lines, fmt.Sprintf("轮次预算：%d/%d", flowState.RoundUsed, flowState.MaxRounds))
	}
	return strings.TrimSpace(strings.Join(lines, "\n"))
}

func buildCurrentPlanStepPinnedMarkdown(step newagentmodel.PlanStep, current, total int) string {
	lines := make([]string, 0, 4)
	lines = append(lines, fmt.Sprintf("步骤进度：第 %d/%d 步", current, total))

	content := compactExecutePinnedText(step.Content)
	if content == "" {
		content = "（空）"
	}
	lines = append(lines, "步骤内容："+content)

	doneWhen := compactExecutePinnedText(step.DoneWhen)
	if doneWhen != "" {
		lines = append(lines, "完成判定："+doneWhen)
	}

	return strings.TrimSpace(strings.Join(lines, "\n"))
}

func compactExecutePinnedText(text string) string {
	text = strings.TrimSpace(text)
	if text == "" {
		return ""
	}
	text = strings.ReplaceAll(text, "\r\n", "\n")
	text = strings.ReplaceAll(text, "\n", "；")
	return strings.TrimSpace(text)
}
