package room

import (
	"context"
	"fmt"
	"log"
	"strings"
	"sync"

	"github.com/sdaduanbilei/agent-team/internal/agent"
	"github.com/sdaduanbilei/agent-team/internal/llm"
	"github.com/sdaduanbilei/agent-team/internal/skill"
	"github.com/sdaduanbilei/agent-team/internal/store"
)

func (r *Room) runMembersParallel(ctx context.Context, assignments map[string]string, board *SharedBoard, skillXML string) map[string]string {
	results := make(map[string]string)
	var mu sync.Mutex
	var wg sync.WaitGroup

	tools := skill.ToTools(r.skillMeta)

	for memberName, task := range assignments {
		wg.Add(1)
		go func(name, t string) {
			defer wg.Done()
			member, ok := r.members[name]
			if !ok {
				return
			}
			r.setStatus(StatusWorking, member.Config.Name, t)
			r.emit(Event{Type: EvtTaskAssign, From: r.master.Config.Name, To: name, Task: t})

			// 构建系统提示上下文
			memberSystem, taskMsg, targetFile := r.buildMemberContext(name, t, board, tools, skillXML)

			// 标记已查阅 workspace 文件
			wsFiles := r.listWorkspaceFiles()
			for i, f := range wsFiles {
				r.emit(Event{Type: EvtFileRead, Agent: name, Filename: f})
				if i == 0 {
					r.setStatus(StatusWorking, name, fmt.Sprintf("正在阅读 %s ...", f))
				}
			}
			memberMsgs := []llm.Message{
				llm.NewMsg("system", memberSystem),
				llm.NewMsg("user", taskMsg),
			}

			var finalReply string
			if targetFile != nil {
				// FILE CALL: 静默调用，不流式输出到聊天
				docName := strings.TrimSuffix(targetFile.Path, ".md")
				r.emit(Event{Type: EvtFileWorking, Agent: name, Filename: targetFile.Path, Title: docName})
				finalReply = r.runToolLoop(ctx, name, member, &memberMsgs, tools, &mu, results)
			} else if dynDir, dynOwner, _ := r.getDynamicFileInfo(); dynDir != "" && dynOwner == name && r.allStaticFilesDone() {
				// 动态章节写作：也是静默文档调用
				r.emit(Event{Type: EvtFileWorking, Agent: name, Filename: "章节", Title: "章节"})
				finalReply = r.runToolLoop(ctx, name, member, &memberMsgs, tools, &mu, results)
			} else {
				// CHAT CALL: 保持现有流式输出逻辑
				finalReply = r.runToolLoop(ctx, name, member, &memberMsgs, tools, &mu, results)
			}

			if r.memberConvos == nil {
				r.memberConvos = make(map[string][]llm.Message)
			}
			r.memberConvos[name] = memberMsgs
			r.memberConvos[name] = append(r.memberConvos[name], llm.NewMsg("assistant", finalReply))

			// Caller-Decided 输出路由
			r.routeMemberOutput(ctx, name, t, member, finalReply, targetFile, board, &mu, results)

			// 异步保存成员记忆
			go r.updateMemberMemory(context.Background(), member, t, finalReply)
		}(memberName, task)
	}
	wg.Wait()

	return results
}

// buildMemberContext 构建成员的系统提示和任务消息
func (r *Room) buildMemberContext(name, task string, board *SharedBoard, tools []llm.Tool, skillXML string) (system, taskMsg string, targetFile *ProjectFile) {
	boardCtx := board.ToContext()
	var extraCtx string
	if len(tools) == 0 {
		extraCtx = skillXML
	}
	if boardCtx != "" {
		if extraCtx != "" {
			extraCtx = boardCtx + "\n\n" + extraCtx
		} else {
			extraCtx = boardCtx
		}
	}
	teamCtx := r.buildTeamXML()
	if teamCtx != "" {
		if extraCtx != "" {
			extraCtx = teamCtx + "\n\n" + extraCtx
		} else {
			extraCtx = teamCtx
		}
	}
	if r.systemRules != "" {
		if extraCtx != "" {
			extraCtx = r.systemRules + "\n\n" + extraCtx
		} else {
			extraCtx = r.systemRules
		}
	}
	if projectCtx := r.buildProjectContext(name); projectCtx != "" {
		if extraCtx != "" {
			extraCtx = extraCtx + "\n\n" + projectCtx
		} else {
			extraCtx = projectCtx
		}
	}

	member := r.members[name]
	system = member.BuildSystemPrompt(extraCtx)

	taskMsg = task
	log.Printf("[room %s] buildMemberContext for %s: projectTemplate=%v", r.Config.Name, name, r.projectTemplate != nil)
	if wsCtx := r.buildWorkspaceContext(); wsCtx != "" {
		taskMsg = task + "\n\n" + wsCtx
	}
	if r.memberArtifacts != nil {
		if _, hasDoc := r.memberArtifacts[name]; hasDoc {
			taskMsg += "\n\n" + r.Prompt.R("member_update_doc")
		}
	}
	// 优先从任务描述中解析目标文件（支持修订已有文件）
	targetFile = r.parseTargetFileFromTask(name, task)
	if targetFile == nil {
		// Caller-Decided: 预先确定目标文件
		targetFile = r.findMemberTargetFile(name)
	}
	if targetFile != nil {
		docName := strings.TrimSuffix(targetFile.Path, ".md")
		taskMsg += "\n\n" + r.Prompt.Render("file_call_member", map[string]string{
			"FilePath": targetFile.Path,
			"DocName":  docName,
		})
	}
	return
}

// runToolLoop 执行 tool calling 循环，返回最终回复
func (r *Room) runToolLoop(ctx context.Context, name string, member *agent.Agent, memberMsgs *[]llm.Message, tools []llm.Tool, mu *sync.Mutex, results map[string]string) string {
	var finalReply string
	for round := 0; round < 10; round++ {
		result, err := member.ChatWithTools(ctx, *memberMsgs, tools, nil)
		if err != nil {
			mu.Lock()
			results[name] = fmt.Sprintf("[error] %v", err)
			mu.Unlock()
			return ""
		}
		r.emitUsage(name, result.Usage)

		if len(result.ToolCalls) == 0 {
			finalReply = result.Content
			break
		}

		assistantMsg := llm.Message{
			Role:      "assistant",
			Content:   result.Content,
			ToolCalls: result.ToolCalls,
		}
		*memberMsgs = append(*memberMsgs, assistantMsg)

		var toolNames []string
		for _, tc := range result.ToolCalls {
			toolNames = append(toolNames, tc.Function.Name)
		}
		r.emit(Event{Type: EvtAgentMessage, Agent: name, Role: "tool_use",
			Content: strings.Join(toolNames, ", "), Streaming: true})

		for _, tc := range result.ToolCalls {
			toolResult := r.executeToolCall(tc)
			*memberMsgs = append(*memberMsgs, llm.NewToolResultMsg(tc.ID, toolResult))
		}

		r.emit(Event{Type: EvtAgentMessage, Agent: name, Role: "tool_use",
			Content: "thinking", Streaming: true})
	}

	// 关闭 tool_use 状态
	r.emit(Event{Type: EvtAgentMessage, Agent: name, Role: "tool_use",
		Content: "", Streaming: false})

	// 强制无 tools 生成总结
	if finalReply == "" {
		*memberMsgs = append(*memberMsgs, llm.NewMsg("user", r.Prompt.R("tool_loop_summarize")))
		result, err := member.ChatWithTools(ctx, *memberMsgs, nil, nil)
		if err == nil && result.Content != "" {
			finalReply = result.Content
			r.emitUsage(name, result.Usage)
		}
	}
	if finalReply == "" {
		finalReply = "[任务执行完成，但未产生文本回复]"
	}
	return finalReply
}

// routeMemberOutput 处理成员输出路由（file call 或 chat call）
func (r *Room) routeMemberOutput(ctx context.Context, name, task string, member *agent.Agent, finalReply string, targetFile *ProjectFile, board *SharedBoard, mu *sync.Mutex, results map[string]string) {
	if targetFile != nil {
		log.Printf("[room %s] FILE CALL for %s → %s (%d chars)", r.Config.Name, name, targetFile.Path, len(finalReply))
		// FILE CALL: 直接保存到已知目标文件
		content := strings.TrimSpace(finalReply)
		if !strings.HasPrefix(content, "# ") {
			content = "# " + strings.TrimSuffix(targetFile.Path, ".md") + "\n\n" + content
		}
		r.saveWorkspace(targetFile.Path, content)
		docName := strings.TrimSuffix(targetFile.Path, ".md")
		r.emit(Event{Type: EvtArtifact, Agent: name, Filename: targetFile.Path, Title: docName})
		r.emit(Event{Type: EvtFileDone, Agent: name, Filename: targetFile.Path, Title: docName})
		r.emit(Event{Type: EvtTaskDone, Agent: name, Task: task})
		if r.memberArtifacts == nil {
			r.memberArtifacts = make(map[string]string)
		}
		r.memberArtifacts[name] = targetFile.Path

		if r.Store != nil {
			r.Store.InsertMessage(&store.Message{
				RoomID: r.Config.Name, Agent: name, Role: "member",
				Content: docName, Filename: targetFile.Path, PartType: "document",
				GroupID: &r.currentGroupID,
			})
		}

		// 文档已保存，发送静态完成消息到聊天
		statusMsg := fmt.Sprintf("《%s》已完成，@master 请查阅。", docName)
		r.emit(Event{Type: EvtAgentMessage, Agent: name, Role: "member", Content: statusMsg, NoStore: true})
		if r.Store != nil {
			r.Store.InsertMessage(&store.Message{
				RoomID: r.Config.Name, Agent: name, Role: "member",
				Content: statusMsg, PartType: "text",
				GroupID: &r.currentGroupID,
			})
		}
		mu.Lock()
		results[name] = statusMsg
		mu.Unlock()
		r.AppendHistory("member", name, finalReply)
		board.Add(name, statusMsg, "draft")
	} else {
		// CHAT CALL: 走旧路由（targetFile 为 nil）
		log.Printf("[room %s] CHAT CALL for %s (no targetFile, %d chars)", r.Config.Name, name, len(finalReply))
		savedPath, routed := r.saveAgentOutput(name, finalReply, task)
		if routed {
			if r.Store != nil {
				title := extractTitle(finalReply)
				r.Store.InsertMessage(&store.Message{
					RoomID: r.Config.Name, Agent: name, Role: "member",
					Content: title, Filename: savedPath, PartType: "document",
					GroupID: &r.currentGroupID,
				})
			}
			docTitle := extractTitle(finalReply)
			statusMsg := fmt.Sprintf("《%s》已完成，@master 请查阅。", docTitle)
			r.emit(Event{Type: EvtAgentMessage, Agent: name, Role: "member", Content: statusMsg, NoStore: true})
			if r.Store != nil {
				r.Store.InsertMessage(&store.Message{
					RoomID: r.Config.Name, Agent: name, Role: "member",
					Content: statusMsg, PartType: "text",
					GroupID: &r.currentGroupID,
				})
			}
			mu.Lock()
			results[name] = statusMsg
			mu.Unlock()
			r.AppendHistory("member", name, finalReply)
			board.Add(name, statusMsg, "draft")
		} else {
			mu.Lock()
			results[name] = finalReply
			mu.Unlock()
			r.AppendHistory("member", name, finalReply)
			if strings.TrimSpace(finalReply) != "" {
				board.Add(name, finalReply, "draft")
			}
		}
	}
}

// runSecondRound 检查成员间委派，自动分派第二轮
func (r *Room) runSecondRound(ctx context.Context, results map[string]string, board *SharedBoard, tools []llm.Tool, skillXML string, mu *sync.Mutex) {
	secondRound := make(map[string]string)
	for _, result := range results {
		subAssignments := parseAssignments(result)
		for name, task := range subAssignments {
			if _, isMember := r.members[name]; isMember {
				if _, alreadyDone := results[name]; !alreadyDone {
					secondRound[name] = task
				}
			}
		}
	}
	if len(secondRound) == 0 {
		return
	}

	log.Printf("[room %s] 检测到成员间委派，执行第二轮: %v", r.Config.Name, secondRound)
	var wg sync.WaitGroup
	for memberName, task := range secondRound {
		wg.Add(1)
		go func(name, t string) {
			defer wg.Done()
			member, ok := r.members[name]
			if !ok {
				return
			}
			r.setStatus(StatusWorking, member.Config.Name, t)
			r.emit(Event{Type: EvtTaskAssign, From: "team", To: name, Task: t})

			memberSystem, taskMsg, _ := r.buildMemberContext(name, t, board, tools, skillXML)
			wsFiles := r.listWorkspaceFiles()
			for i, f := range wsFiles {
				r.emit(Event{Type: EvtFileRead, Agent: name, Filename: f})
				if i == 0 {
					r.setStatus(StatusWorking, name, fmt.Sprintf("正在阅读 %s ...", f))
				}
			}
			memberMsgs := []llm.Message{
				llm.NewMsg("system", memberSystem),
				llm.NewMsg("user", taskMsg),
			}

			finalReply := r.runToolLoop(ctx, name, member, &memberMsgs, tools, mu, results)

			statusMsg, routed := r.saveAgentOutput(name, finalReply, t)
			if routed {
				mu.Lock()
				results[name] = statusMsg
				mu.Unlock()
				r.AppendHistory("member", name, finalReply)
				if strings.TrimSpace(statusMsg) != "" {
					board.Add(name, statusMsg, "draft")
				}
			} else {
				mu.Lock()
				results[name] = finalReply
				mu.Unlock()
				r.AppendHistory("member", name, finalReply)
				if strings.TrimSpace(finalReply) != "" {
					board.Add(name, finalReply, "draft")
				}
			}

			go r.updateMemberMemory(context.Background(), member, t, finalReply)
		}(memberName, task)
	}
	wg.Wait()
}

func (r *Room) runChallengeRound(ctx context.Context, board *SharedBoard, skillXML string) {
	var challengers []string
	for name, member := range r.members {
		if member.Config.CanChallenge {
			challengers = append(challengers, name)
		}
	}
	if len(challengers) == 0 {
		return
	}

	boardCtx := board.ToContext()
	if boardCtx == "" && len(r.listWorkspaceFiles()) == 0 {
		return
	}

	var wg sync.WaitGroup
	for _, name := range challengers {
		wg.Add(1)
		go func(n string) {
			defer wg.Done()
			member := r.members[n]
			extraCtx := boardCtx + "\n\n" + skillXML
			if wsCtx := r.buildWorkspaceContext(); wsCtx != "" {
				extraCtx = wsCtx + "\n\n" + extraCtx
			}
			teamCtx := r.buildTeamXML()
			if teamCtx != "" {
				extraCtx = teamCtx + "\n\n" + extraCtx
			}
			if r.systemRules != "" {
				extraCtx = r.systemRules + "\n\n" + extraCtx
			}
			if projectCtx := r.buildProjectContext(n); projectCtx != "" {
				extraCtx = extraCtx + "\n\n" + projectCtx
			}
			memberSystem := member.BuildSystemPrompt(extraCtx)
			memberMsgs := []llm.Message{
				llm.NewMsg("system", memberSystem+"\n\n"+r.Prompt.R("challenge_review")),
				llm.NewMsg("user", "请审阅 workspace 中的文档并给出你的专业反馈。"),
			}
			var reply strings.Builder
			_, usage, err := member.ChatWithUsage(ctx, memberMsgs, func(token string) {
				reply.WriteString(token)
				r.emit(Event{Type: EvtAgentMessage, Agent: n, Role: "challenge", Content: token, Streaming: true})
			})
			if err != nil {
				return
			}
			r.emitUsage(n, usage)
			r.emit(Event{Type: EvtAgentMessage, Agent: n, Role: "challenge", Content: "", Streaming: false, NoStore: true})
			result := reply.String()
			if r.Store != nil && result != "" {
				r.Store.InsertMessage(&store.Message{
					RoomID: r.Config.Name, Agent: n, Role: "challenge",
					Content: result, PartType: "text",
					GroupID: &r.currentGroupID,
				})
			}
			if strings.Contains(result, "CHALLENGE:") {
				board.Add(n, result, "challenge")
				r.AppendHistory("challenge", n, result)
			}
		}(name)
	}
	wg.Wait()
}
