package newagentnode

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

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

const (
	confirmStageName     = "confirm"
	confirmStatusBlockID = "confirm.status"
)

// ConfirmNodeInput 描述确认节点单轮运行所需的最小依赖。
//
// 职责边界：
// 1. 不需要 LLM Client — 确认内容由已有状态机械格式化，不调模型；
// 2. RuntimeState 提供计划步骤和待确认工具快照；
// 3. ChunkEmitter 负责推送确认事件到前端。
type ConfirmNodeInput struct {
	RuntimeState        *newagentmodel.AgentRuntimeState
	ConversationContext *newagentmodel.ConversationContext
	ChunkEmitter        *newagentstream.ChunkEmitter
}

// RunConfirmNode 执行一轮确认节点逻辑。
//
// 核心职责：
// 1. 判断确认来源：有 PendingConfirmTool → 工具确认；有 PlanSteps → 计划确认；
// 2. 机械格式化确认内容（不需要 LLM 调用）；
// 3. 推送确认事件 EmitConfirmRequest → 前端渲染确认卡片；
// 4. 调用 OpenConfirmInteraction 固化中断快照，Phase 自动变为 interrupted。
//
// 设计原则：
// 1. 不等待用户响应 — 等待是 interruptNode 的职责；
// 2. 不执行任何工具 — 只固化"意图"，执行留给恢复后的 Execute；
// 3. Confirm 是图里唯一负责"生成确认事件 + 固化快照"的地方，上游节点只设 Phase。
func RunConfirmNode(ctx context.Context, input ConfirmNodeInput) error {
	runtimeState, _, emitter, err := prepareConfirmNodeInput(input)
	if err != nil {
		return err
	}
	flowState := runtimeState.EnsureCommonState()

	// 优先处理工具确认（Execute 发起的写操作确认）。
	if runtimeState.PendingConfirmTool != nil {
		return handleToolConfirm(ctx, runtimeState, flowState, emitter)
	}

	// 其次处理计划确认（Plan 完成后的整体验收）。
	if flowState.HasPlan() {
		return handlePlanConfirm(ctx, runtimeState, flowState, emitter)
	}

	// 既没有工具也没有计划 → 异常状态，不应到达此处。
	return fmt.Errorf("confirm node: 没有可确认的内容（无计划、无待确认工具）")
}

// handlePlanConfirm 处理计划确认。
//
// 流程：
// 1. 从 flowState.PlanSteps 格式化可读摘要；
// 2. 推送确认事件到前端；
// 3. 调用 OpenConfirmInteraction 固化快照（无 PendingTool）。
func handlePlanConfirm(
	ctx context.Context,
	runtimeState *newagentmodel.AgentRuntimeState,
	flowState *newagentmodel.CommonState,
	emitter *newagentstream.ChunkEmitter,
) error {
	summary := buildPlanSummary(flowState.PlanSteps)
	interactionID := generateConfirmInteractionID(flowState)

	if err := emitter.EmitConfirmRequest(
		ctx, confirmStatusBlockID, confirmStageName,
		interactionID,
		"计划确认",
		summary,
		newagentstream.DefaultPseudoStreamOptions(),
	); err != nil {
		return fmt.Errorf("计划确认事件推送失败: %w", err)
	}

	runtimeState.OpenConfirmInteraction(
		interactionID,
		summary,
		"plan",
		nil,
	)

	_ = emitter.EmitStatus(
		confirmStatusBlockID, confirmStageName,
		"plan_confirm", "计划已生成，等待用户确认。", false,
	)
	return nil
}

// handleToolConfirm 处理工具确认。
//
// 流程：
// 1. 从 PendingConfirmTool 构建确认摘要；
// 2. 推送确认事件到前端；
// 3. 调用 OpenConfirmInteraction 固化快照（含 PendingTool）；
// 4. 清空 PendingConfirmTool 临时邮箱。
func handleToolConfirm(
	ctx context.Context,
	runtimeState *newagentmodel.AgentRuntimeState,
	flowState *newagentmodel.CommonState,
	emitter *newagentstream.ChunkEmitter,
) error {
	pendingTool := runtimeState.PendingConfirmTool
	summary := buildToolConfirmSummary(pendingTool)
	interactionID := generateConfirmInteractionID(flowState)

	if err := emitter.EmitConfirmRequest(
		ctx, confirmStatusBlockID, confirmStageName,
		interactionID,
		"操作确认",
		summary,
		newagentstream.DefaultPseudoStreamOptions(),
	); err != nil {
		return fmt.Errorf("工具确认事件推送失败: %w", err)
	}

	runtimeState.OpenConfirmInteraction(
		interactionID,
		summary,
		"execute",
		pendingTool,
	)

	// 确认快照已固化到 PendingInteraction，清空临时邮箱。
	runtimeState.PendingConfirmTool = nil

	_ = emitter.EmitStatus(
		confirmStatusBlockID, confirmStageName,
		"tool_confirm", "操作等待确认。", false,
	)
	return nil
}

// buildPlanSummary 把 PlanSteps 格式化成人类可读的确认摘要。
func buildPlanSummary(steps []newagentmodel.PlanStep) string {
	var sb strings.Builder
	sb.WriteString(fmt.Sprintf("共 %d 步：\n", len(steps)))
	for i, step := range steps {
		sb.WriteString(fmt.Sprintf("%d. %s", i+1, step.Content))
		if step.DoneWhen != "" {
			sb.WriteString(fmt.Sprintf("（完成条件：%s）", step.DoneWhen))
		}
		sb.WriteString("\n")
	}
	return strings.TrimSpace(sb.String())
}

// buildToolConfirmSummary 从工具快照构建确认摘要。
func buildToolConfirmSummary(tool *newagentmodel.PendingToolCallSnapshot) string {
	if tool == nil {
		return "待确认操作"
	}
	if tool.Summary != "" {
		return tool.Summary
	}
	detail := fmt.Sprintf("即将执行工具：%s", tool.ToolName)
	if tool.ArgsJSON != "" {
		var args map[string]any
		if json.Unmarshal([]byte(tool.ArgsJSON), &args) == nil && len(args) > 0 {
			detail += fmt.Sprintf("，参数：%s", tool.ArgsJSON)
		}
	}
	return detail
}

// generateConfirmInteractionID 生成确认交互的唯一标识。
func generateConfirmInteractionID(flowState *newagentmodel.CommonState) string {
	prefix := flowState.TraceID
	if prefix == "" {
		prefix = "confirm"
	}
	return fmt.Sprintf("%s-%d", prefix, time.Now().UnixMilli())
}

// prepareConfirmNodeInput 校验并准备确认节点的运行态依赖。
func prepareConfirmNodeInput(input ConfirmNodeInput) (
	*newagentmodel.AgentRuntimeState,
	*newagentmodel.ConversationContext,
	*newagentstream.ChunkEmitter,
	error,
) {
	if input.RuntimeState == nil {
		return nil, nil, nil, fmt.Errorf("confirm node: runtime state 不能为空")
	}
	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
}
