package skills

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

	"agent-desk/internal/ai"
	"agent-desk/internal/models"

	"github.com/mlogclub/simple/common/strs"
)

const routeSkillSystemPrompt = `你是客服技能路由器。你只能在候选 Skill 中选择一个最合适的 skillId，或者返回 NONE。
只有当用户问题与 Skill 的职责边界明确匹配时才选择；
如果不明确、信息不足、多个 Skill 都不够确定，就返回 NONE。
输出只能是 skillId 或 NONE，不能输出其他内容。`

func routeSkillWithLLM(ctx context.Context, runtimeCtx RuntimeContext, candidates []models.SkillDefinition) (*models.SkillDefinition, *RouteTrace, error) {
	trace := &RouteTrace{Status: "started"}
	if len(candidates) == 0 {
		trace.Status = "no_candidate"
		return nil, trace, nil
	}
	if strs.IsBlank(runtimeCtx.UserMessage) {
		trace.Status = "empty_user_message"
		return nil, trace, nil
	}
	userPrompt := buildSkillRoutePrompt(runtimeCtx.UserMessage, candidates)
	startedAt := time.Now()
	result, err := ai.LLM.ChatWithConfig(ctx, runtimeCtx.AIConfig, routeSkillSystemPrompt, userPrompt)
	trace.LatencyMs = time.Since(startedAt).Milliseconds()
	if err != nil {
		trace.Status = "route_error"
		trace.Error = err.Error()
		return nil, trace, err
	}
	decision := normalizeRouteDecision(result.Content)
	trace.RawDecision = strings.TrimSpace(result.Content)
	if decision == "" || decision == "NONE" {
		trace.Status = "not_matched"
		return nil, trace, nil
	}
	selectedID, parseErr := strconv.ParseInt(decision, 10, 64)
	if parseErr != nil || selectedID <= 0 {
		trace.Status = "invalid_decision"
		trace.Error = fmt.Sprintf("invalid route decision: %s", decision)
		return nil, trace, nil
	}
	for _, item := range candidates {
		if item.ID == selectedID {
			trace.Status = "llm_selected"
			trace.SelectedSkillID = item.ID
			return &item, trace, nil
		}
	}
	trace.Status = "invalid_decision"
	trace.Error = fmt.Sprintf("invalid route decision: %s", decision)
	return nil, trace, nil
}

func buildSkillRoutePrompt(userMessage string, candidates []models.SkillDefinition) string {
	lines := make([]string, 0, len(candidates)+4)
	lines = append(lines, "用户问题：")
	lines = append(lines, strings.TrimSpace(userMessage))
	lines = append(lines, "")
	lines = append(lines, "候选 Skills：")
	for _, item := range candidates {
		line := fmt.Sprintf("- skillId=%d; name=%s; description=%s", item.ID, strings.TrimSpace(item.Name), strings.TrimSpace(item.Description))
		if examples := parseSkillExamples(item.Examples); len(examples) > 0 {
			line += "; examples=" + strings.Join(examples, " | ")
		}
		lines = append(lines, line)
	}
	lines = append(lines, "")
	lines = append(lines, "请只输出一个 skillId 或 NONE。")
	return strings.Join(lines, "\n")
}

func parseSkillExamples(raw string) []string {
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return nil
	}
	var items []string
	if err := json.Unmarshal([]byte(raw), &items); err != nil {
		return nil
	}
	ret := make([]string, 0, len(items))
	for _, item := range items {
		item = strings.TrimSpace(item)
		if item == "" {
			continue
		}
		ret = append(ret, item)
		if len(ret) >= 3 {
			break
		}
	}
	return ret
}

func normalizeRouteDecision(raw string) string {
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return ""
	}
	if idx := strings.Index(raw, "\n"); idx >= 0 {
		raw = raw[:idx]
	}
	raw = strings.TrimSpace(raw)
	raw = strings.Trim(raw, "`")
	raw = strings.TrimSpace(raw)
	raw = strings.Trim(raw, "\"'")
	if strings.EqualFold(raw, "NONE") {
		return "NONE"
	}
	return raw
}
