package handler

import (
	"fkteams/agents"
	agentcommon "fkteams/agents/common"
	"fkteams/channels"
	"fkteams/config"
	"fkteams/g"
	"fkteams/log"
	"fkteams/memory"
	"fkteams/tools"
	"fkteams/tools/mcp"
	"net/http"
	"runtime"
	"strings"

	"github.com/gin-gonic/gin"
)

// maskAPIKey 对 API Key 做脱敏处理，只保留后 4 位
func maskAPIKey(key string) string {
	if len(key) <= 4 {
		return "****"
	}
	return strings.Repeat("*", len(key)-4) + key[len(key)-4:]
}

// isMasked 检测字段值是否为脱敏后的掩码值
func isMasked(s string) bool {
	return strings.Contains(s, "**")
}

const sensitivePassword = "***"

// GetConfigHandler 获取配置（敏感字段脱敏）
func GetConfigHandler() gin.HandlerFunc {
	return func(c *gin.Context) {
		cfg := config.Get()

		// 深拷贝并脱敏
		resp := *cfg

		// 处理模型 APIKey：不返回真实密钥，仅标记是否已配置
		models := make([]config.ModelConfig, len(cfg.Models))
		for i, m := range cfg.Models {
			models[i] = m
			models[i].HasAPIKey = m.APIKey != ""
			models[i].APIKey = ""
		}
		resp.Models = models

		// 脱敏 Auth
		if resp.Server.Auth.Password != "" {
			resp.Server.Auth.Password = sensitivePassword
		}
		if resp.Server.Auth.Secret != "" {
			resp.Server.Auth.Secret = sensitivePassword
		}

		// 脱敏 SSH
		if resp.Agents.SSHVisitor.Password != "" {
			resp.Agents.SSHVisitor.Password = sensitivePassword
		}

		// 脱敏 Channels
		if resp.Channels.QQ.AppSecret != "" {
			resp.Channels.QQ.AppSecret = sensitivePassword
		}
		if resp.Channels.Discord.Token != "" {
			resp.Channels.Discord.Token = maskAPIKey(resp.Channels.Discord.Token)
		}

		OK(c, resp)
	}
}

// UpdateConfigHandler 更新配置（敏感字段合并旧值）
func UpdateConfigHandler() gin.HandlerFunc {
	return func(c *gin.Context) {
		var newCfg config.Config
		if err := c.ShouldBindJSON(&newCfg); err != nil {
			Fail(c, http.StatusBadRequest, "invalid config: "+err.Error())
			return
		}

		oldCfg := config.Get()

		// 校验模型名称唯一性
		modelNames := make(map[string]bool, len(newCfg.Models))
		for _, m := range newCfg.Models {
			if m.Name == "" {
				continue
			}
			if modelNames[m.Name] {
				Fail(c, http.StatusBadRequest, "duplicate model name: "+m.Name)
				return
			}
			modelNames[m.Name] = true
		}

		// 合并敏感字段：前端传空字符串时保留旧值
		for i := range newCfg.Models {
			if newCfg.Models[i].APIKey == "" {
				lookupName := newCfg.Models[i].OriginalName
				if lookupName == "" {
					lookupName = newCfg.Models[i].Name
				}
				restored := false
				for _, old := range oldCfg.Models {
					if old.Name == lookupName {
						newCfg.Models[i].APIKey = old.APIKey
						restored = true
						break
					}
				}
				if !restored && i < len(oldCfg.Models) {
					newCfg.Models[i].APIKey = oldCfg.Models[i].APIKey
				}
			}
		}
		if newCfg.Server.Auth.Password == sensitivePassword {
			newCfg.Server.Auth.Password = oldCfg.Server.Auth.Password
		}
		if newCfg.Server.Auth.Secret == sensitivePassword {
			newCfg.Server.Auth.Secret = oldCfg.Server.Auth.Secret
		}
		if newCfg.Agents.SSHVisitor.Password == sensitivePassword {
			newCfg.Agents.SSHVisitor.Password = oldCfg.Agents.SSHVisitor.Password
		}
		if newCfg.Channels.QQ.AppSecret == sensitivePassword {
			newCfg.Channels.QQ.AppSecret = oldCfg.Channels.QQ.AppSecret
		}
		if isMasked(newCfg.Channels.Discord.Token) {
			newCfg.Channels.Discord.Token = oldCfg.Channels.Discord.Token
		}

		// 检测 Auth 是否变更
		authChanged := oldCfg.Server.Auth.Username != newCfg.Server.Auth.Username ||
			oldCfg.Server.Auth.Password != newCfg.Server.Auth.Password ||
			oldCfg.Server.Auth.Secret != newCfg.Server.Auth.Secret ||
			oldCfg.Server.Auth.Enabled != newCfg.Server.Auth.Enabled

		// 保存并重载
		if err := config.Save(&newCfg); err != nil {
			Fail(c, http.StatusInternalServerError, "failed to save config: "+err.Error())
			return
		}

		// 重载智能体注册表、清除 Runner 缓存和 MCP 工具缓存
		agents.ReloadRegistry()
		ClearRunnerCache()
		mcp.ClearCache()
		channels.ResetAllBridges()
		resetMemoryLLM()

		OK(c, gin.H{"auth_changed": authChanged})
	}
}

// resetMemoryLLM 使用当前配置重建 MemoryManager 的 LLM 客户端
func resetMemoryLLM() {
	if g.MemoryManager == nil {
		return
	}
	chatModel, err := agentcommon.NewChatModel()
	if err != nil {
		log.Printf("[memory] 重建模型失败，记忆服务继续使用旧模型: %v", err)
		return
	}
	llmClient, err := memory.NewLLMClient(chatModel)
	if err != nil {
		log.Printf("[memory] 适配模型失败，记忆服务继续使用旧模型: %v", err)
		return
	}
	g.MemoryManager.ResetLLM(llmClient)
	log.Println("[memory] 记忆服务模型已更新")
}

// GetToolNamesHandler 获取可用工具名列表
func GetToolNamesHandler() gin.HandlerFunc {
	return func(c *gin.Context) {
		OK(c, tools.GetAllToolNames())
	}
}

// GetTemplateVarsHandler 返回可用的模板变量列表（供前端提示词编辑器补全）
func GetTemplateVarsHandler() gin.HandlerFunc {
	type templateVar struct {
		Name        string `json:"name"`
		Description string `json:"description"`
		Example     string `json:"example"`
	}
	vars := []templateVar{
		{Name: "os_type", Description: "操作系统类型", Example: runtime.GOOS},
		{Name: "os_arch", Description: "系统架构", Example: runtime.GOARCH},
		{Name: "workspace_dir", Description: "工作目录路径", Example: "/path/to/workspace"},
	}
	return func(c *gin.Context) {
		OK(c, vars)
	}
}
