package tools

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

	"github.com/voocel/agentcore/schema"
	"github.com/voocel/ainovel-cli/domain"
	"github.com/voocel/ainovel-cli/state"
)

// References 嵌入的参考资料。
type References struct {
	// V0
	ChapterGuide      string
	HookTechniques    string
	QualityChecklist  string
	OutlineTemplate   string
	CharacterTemplate string
	ChapterTemplate   string
	// V1
	Consistency      string
	ContentExpansion string
	DialogueWriting  string
	// V2
	StyleReference   string // 风格补充参考（可为空）
	LongformPlanning string // 通用长篇规划参考
	Differentiation  string // 通用差异化设计参考
}

// ContextTool 组装当前章节所需上下文。
type ContextTool struct {
	store *state.Store
	refs  References
	style string
}

func NewContextTool(store *state.Store, refs References, style string) *ContextTool {
	return &ContextTool{store: store, refs: refs, style: style}
}

func (t *ContextTool) Name() string { return "novel_context" }
func (t *ContextTool) Description() string {
	return "获取小说创作上下文，包括基础设定、状态数据、前情摘要和写作参考资料"
}
func (t *ContextTool) Label() string { return "加载上下文" }

func (t *ContextTool) Schema() map[string]any {
	return schema.Object(
		schema.Property("chapter", schema.Int("章节号。不传则返回基础设定和模板（供 Architect 使用）")),
	)
}

func (t *ContextTool) Execute(_ context.Context, args json.RawMessage) (json.RawMessage, error) {
	var a struct {
		Chapter int `json:"chapter"`
	}
	if err := json.Unmarshal(args, &a); err != nil {
		return nil, fmt.Errorf("invalid args: %w", err)
	}

	result := make(map[string]any)
	var warnings []string
	seenWarnings := make(map[string]struct{})
	warn := func(scope string, err error) {
		if err == nil || os.IsNotExist(err) {
			return
		}
		msg := fmt.Sprintf("%s 读取失败: %v", scope, err)
		if _, ok := seenWarnings[msg]; ok {
			return
		}
		seenWarnings[msg] = struct{}{}
		warnings = append(warnings, msg)
	}

	// 加载基础设定
	if premise, err := t.store.LoadPremise(); err == nil && premise != "" {
		result["premise"] = premise
	} else {
		warn("premise", err)
	}
	if outline, err := t.store.LoadOutline(); err == nil && outline != nil {
		result["outline"] = outline
	} else {
		warn("outline", err)
	}
	if rules, err := t.store.LoadWorldRules(); err == nil && len(rules) > 0 {
		result["world_rules"] = rules
	} else {
		warn("world_rules", err)
	}

	if a.Chapter > 0 {
		// 根据总章节数计算上下文策略
		profile := domain.NewContextProfile(0)
		progress, err := t.store.LoadProgress()
		warn("progress", err)
		runMeta, err := t.store.LoadRunMeta()
		warn("run_meta", err)
		if runMeta != nil && runMeta.PlanningTier != "" {
			result["planning_tier"] = runMeta.PlanningTier
		}
		if progress != nil && progress.TotalChapters > 0 {
			profile = domain.NewContextProfile(progress.TotalChapters)
		}
		// Layered 以 Progress 的显式标志为准，而非章节数推断
		if progress == nil || !progress.Layered {
			profile.Layered = false
		}

		// 角色加载：Layered 模式优先用快照，回退到原始设定
		if profile.Layered {
			t.loadLayeredCharacters(result, a.Chapter, warn)
		} else {
			t.loadFilteredCharacters(result, a.Chapter, warn)
		}

		// Writer/Editor 模式：加载章节相关上下文
		if entry, err := t.store.GetChapterOutline(a.Chapter); err == nil {
			result["current_chapter_outline"] = entry
		} else {
			warn("current_chapter_outline", err)
		}

		// 摘要加载：分层 vs 扁平窗口
		if profile.Layered {
			t.loadLayeredSummaries(result, a.Chapter, profile.SummaryWindow, warn)
		} else {
			if summaries, err := t.store.LoadRecentSummaries(a.Chapter, profile.SummaryWindow); err == nil && len(summaries) > 0 {
				result["recent_summaries"] = summaries
			} else {
				warn("recent_summaries", err)
			}
		}

		// 时间线：窗口加载
		if timeline, err := t.store.LoadRecentTimeline(a.Chapter, profile.TimelineWindow); err == nil && len(timeline) > 0 {
			result["timeline"] = timeline
		} else {
			warn("timeline", err)
		}
		// foreshadow：只取未回收条目
		if foreshadow, err := t.store.LoadActiveForeshadow(); err == nil && len(foreshadow) > 0 {
			result["foreshadow_ledger"] = foreshadow
		} else {
			warn("foreshadow_ledger", err)
		}
		// relationships：保持全量（pair-key 去重，数据量天然可控）
		if relationships, err := t.store.LoadRelationships(); err == nil && len(relationships) > 0 {
			result["relationship_state"] = relationships
		} else {
			warn("relationship_state", err)
		}
		// 状态变化：最近 2 章
		if changes, err := t.store.LoadRecentStateChanges(a.Chapter, 2); err == nil && len(changes) > 0 {
			result["recent_state_changes"] = changes
		} else {
			warn("recent_state_changes", err)
		}

		// Layered 模式：注入当前卷弧位置 + 弧目标/卷主题
		if profile.Layered && progress != nil {
			pos := map[string]any{
				"volume": progress.CurrentVolume,
				"arc":    progress.CurrentArc,
			}
			if volumes, err := t.store.LoadLayeredOutline(); err == nil {
				for _, v := range volumes {
					if v.Index == progress.CurrentVolume {
						pos["volume_title"] = v.Title
						pos["volume_theme"] = v.Theme
						for _, arc := range v.Arcs {
							if arc.Index == progress.CurrentArc {
								pos["arc_title"] = arc.Title
								pos["arc_goal"] = arc.Goal
								break
							}
						}
						break
					}
				}
			} else {
				warn("layered_outline", err)
			}
			result["position"] = pos
		}

		// 加载进度状态和节奏追踪
		if progress != nil {
			checkpoint := map[string]any{
				"in_progress_chapter": progress.InProgressChapter,
			}
			if len(progress.StrandHistory) > 0 {
				checkpoint["strand_history"] = progress.StrandHistory
			}
			if len(progress.HookHistory) > 0 {
				checkpoint["hook_history"] = progress.HookHistory
			}
			result["checkpoint"] = checkpoint
		}
		// 加载已有的章节构思
		if plan, err := t.store.LoadChapterPlan(a.Chapter); err == nil && plan != nil {
			result["chapter_plan"] = plan
		} else {
			warn("chapter_plan", err)
		}

		// 前章尾部：嵌入前一章末尾 ~800 字，Writer 无需额外调用 read_chapter 获取衔接上文
		if a.Chapter > 1 {
			if prevText, err := t.store.LoadChapterText(a.Chapter - 1); err == nil && prevText != "" {
				runes := []rune(prevText)
				if len(runes) > 800 {
					runes = runes[len(runes)-800:]
				}
				result["previous_tail"] = string(runes)
			}
		}

		// 风格锚点：从前文提取代表性段落
		if anchors := t.store.ExtractStyleAnchors(3); len(anchors) > 0 {
			result["style_anchors"] = anchors
		}

		// 角色声纹：提取出场角色的对话原文片段
		if entry, err := t.store.GetChapterOutline(a.Chapter); err == nil && entry != nil {
			var voiceSamples []map[string]any
			chars, _ := t.store.LoadCharacters()
			for _, c := range chars {
				// 只为 core/important 角色提取声纹
				if c.Tier == "secondary" || c.Tier == "decorative" {
					continue
				}
				samples := t.store.ExtractDialogue(c.Name, c.Aliases, 3)
				if len(samples) > 0 {
					voiceSamples = append(voiceSamples, map[string]any{
						"character": c.Name,
						"samples":   samples,
					})
				}
				if len(voiceSamples) >= 5 {
					break
				}
			}
			if len(voiceSamples) > 0 {
				result["voice_samples"] = voiceSamples
			}
		}

		// 写作参考资料分阶段加载
		result["references"] = t.writerReferences(a.Chapter)
	} else {
		runMeta, err := t.store.LoadRunMeta()
		warn("run_meta", err)
		if runMeta != nil && runMeta.PlanningTier != "" {
			result["planning_tier"] = runMeta.PlanningTier
		}
		// Architect 模式：全量角色 + 模板
		if chars, err := t.store.LoadCharacters(); err == nil && chars != nil {
			result["characters"] = chars
		} else {
			warn("characters", err)
		}
		// Architect 模式下也加载分层大纲（弧级规划需要看全貌）
		if layered, err := t.store.LoadLayeredOutline(); err == nil && len(layered) > 0 {
			result["layered_outline"] = layered
		} else {
			warn("layered_outline", err)
		}
		// 加载已有的弧摘要（弧级规划时需要参考前续弧的内容）
		if volSummaries, err := t.store.LoadAllVolumeSummaries(); err == nil && len(volSummaries) > 0 {
			result["volume_summaries"] = volSummaries
		} else {
			warn("volume_summaries", err)
		}
		result["references"] = t.architectReferences()

		// 基础设定完备性检查
		result["foundation_status"] = t.foundationStatus()
	}

	if len(warnings) > 0 {
		result["_warnings"] = warnings
	}

	// 优先级预算：总大小超过阈值时自动裁剪低优先级数据
	if a.Chapter > 0 {
		trimByBudget(result, 100*1024) // 100KB 预算
	}

	result["_loading_summary"] = buildLoadingSummary(result, a.Chapter)
	return json.Marshal(result)
}

// buildLoadingSummary 从已组装的 result 中统计各项数据量，生成一行可读摘要。
func buildLoadingSummary(result map[string]any, chapter int) string {
	var parts []string

	if chapter > 0 {
		parts = append(parts, fmt.Sprintf("ch=%d", chapter))
	} else {
		parts = append(parts, "architect")
	}
	if tier, ok := result["planning_tier"].(domain.PlanningTier); ok && tier != "" {
		parts = append(parts, fmt.Sprintf("tier=%s", tier))
	}

	// 卷弧位置
	if pos, ok := result["position"].(map[string]any); ok {
		parts = append(parts, fmt.Sprintf("V%dA%d", pos["volume"], pos["arc"]))
	}

	var items []string
	countSlice := func(key string) int {
		if v, ok := result[key]; ok {
			if s, ok := v.([]domain.Character); ok {
				return len(s)
			}
			// 通用 slice 反射
			return sliceLen(v)
		}
		return 0
	}

	// 角色
	if n := countSlice("character_snapshots"); n > 0 {
		items = append(items, fmt.Sprintf("角色:%d(快照)", n))
	} else if n := countSlice("characters"); n > 0 {
		items = append(items, fmt.Sprintf("角色:%d", n))
	}

	// 分层摘要
	if n := countSlice("volume_summaries"); n > 0 {
		items = append(items, fmt.Sprintf("卷摘要:%d", n))
	}
	if n := countSlice("arc_summaries"); n > 0 {
		items = append(items, fmt.Sprintf("弧摘要:%d", n))
	}
	if n := countSlice("recent_summaries"); n > 0 {
		items = append(items, fmt.Sprintf("章摘要:%d", n))
	}

	// 分层大纲
	if n := countSlice("layered_outline"); n > 0 {
		items = append(items, fmt.Sprintf("分层大纲:%d卷", n))
	}

	// 状态数据
	if n := countSlice("timeline"); n > 0 {
		items = append(items, fmt.Sprintf("时间线:%d", n))
	}
	if n := countSlice("foreshadow_ledger"); n > 0 {
		items = append(items, fmt.Sprintf("伏笔:%d", n))
	}
	if n := countSlice("relationship_state"); n > 0 {
		items = append(items, fmt.Sprintf("关系:%d", n))
	}
	if n := countSlice("recent_state_changes"); n > 0 {
		items = append(items, fmt.Sprintf("状态变化:%d", n))
	}
	if _, ok := result["previous_tail"]; ok {
		items = append(items, "前章尾部:ok")
	}

	// 参考资料
	if refs, ok := result["references"].(map[string]string); ok && len(refs) > 0 {
		items = append(items, fmt.Sprintf("参考:%d项", len(refs)))
	}
	if warnings, ok := result["_warnings"].([]string); ok && len(warnings) > 0 {
		items = append(items, fmt.Sprintf("告警:%d", len(warnings)))
	}
	if trimmed, ok := result["_trimmed"].([]string); ok && len(trimmed) > 0 {
		items = append(items, fmt.Sprintf("裁剪:%s", strings.Join(trimmed, ",")))
	}

	if len(items) > 0 {
		parts = append(parts, strings.Join(items, " "))
	}
	return strings.Join(parts, " | ")
}

// sliceLen 对 any 类型尝试取 slice 长度。
func sliceLen(v any) int {
	switch s := v.(type) {
	case []domain.ChapterSummary:
		return len(s)
	case []domain.ArcSummary:
		return len(s)
	case []domain.VolumeSummary:
		return len(s)
	case []domain.CharacterSnapshot:
		return len(s)
	case []domain.TimelineEvent:
		return len(s)
	case []domain.ForeshadowEntry:
		return len(s)
	case []domain.RelationshipEntry:
		return len(s)
	case []domain.StateChange:
		return len(s)
	case []domain.VolumeOutline:
		return len(s)
	case []domain.Character:
		return len(s)
	default:
		return 0
	}
}

// loadFilteredCharacters 按 Tier 和场景出场过滤角色。
// core/important 始终返回；secondary/decorative 只在当前章节大纲提及时返回。
func (t *ContextTool) loadFilteredCharacters(result map[string]any, chapter int, warn func(string, error)) {
	chars, err := t.store.LoadCharacters()
	if err != nil {
		warn("characters", err)
		return
	}
	if len(chars) == 0 {
		return
	}

	// 获取当前章节大纲的场景描述，用于匹配次要角色
	entry, err := t.store.GetChapterOutline(chapter)
	if err != nil {
		warn("current_chapter_outline", err)
		result["characters"] = chars
		return
	}
	sceneText := strings.Join(entry.Scenes, " ") + " " + entry.CoreEvent + " " + entry.Title

	var filtered []domain.Character
	for _, c := range chars {
		switch c.Tier {
		case "secondary", "decorative":
			if matchCharacter(sceneText, c) {
				filtered = append(filtered, c)
			}
		default: // core, important, 或未设置
			filtered = append(filtered, c)
		}
	}
	result["characters"] = filtered
}

// matchCharacter 检查场景文本中是否包含角色的正式名或任一别名。
func matchCharacter(text string, c domain.Character) bool {
	if strings.Contains(text, c.Name) {
		return true
	}
	for _, alias := range c.Aliases {
		if strings.Contains(text, alias) {
			return true
		}
	}
	return false
}

// loadLayeredSummaries 分层摘要加载：卷摘要 + 当前卷弧摘要 + 弧内章摘要。
func (t *ContextTool) loadLayeredSummaries(result map[string]any, chapter, summaryWindow int, warn func(string, error)) {
	vol, arc, err := t.store.LocateChapter(chapter)
	if err != nil {
		warn("layered_outline_position", err)
		// 回退到扁平模式
		if summaries, err := t.store.LoadRecentSummaries(chapter, summaryWindow); err == nil && len(summaries) > 0 {
			result["recent_summaries"] = summaries
		} else {
			warn("recent_summaries", err)
		}
		return
	}

	// 1. 已完成卷的卷摘要
	if volSummaries, err := t.store.LoadAllVolumeSummaries(); err == nil && len(volSummaries) > 0 {
		result["volume_summaries"] = volSummaries
	} else {
		warn("volume_summaries", err)
	}

	// 2. 当前卷内已完成弧的弧摘要（不含当前弧）
	if arcSummaries, err := t.store.LoadArcSummaries(vol); err == nil && len(arcSummaries) > 0 {
		var prior []domain.ArcSummary
		for _, s := range arcSummaries {
			if s.Arc < arc {
				prior = append(prior, s)
			}
		}
		if len(prior) > 0 {
			result["arc_summaries"] = prior
		}
	} else {
		warn("arc_summaries", err)
	}

	// 3. 当前弧内最近 N 章的章摘要
	if summaries, err := t.store.LoadRecentSummaries(chapter, summaryWindow); err == nil && len(summaries) > 0 {
		result["recent_summaries"] = summaries
	} else {
		warn("recent_summaries", err)
	}
}

// loadLayeredCharacters Layered 模式下的角色加载：优先用最近快照，回退到原始设定 + Tier 过滤。
func (t *ContextTool) loadLayeredCharacters(result map[string]any, chapter int, warn func(string, error)) {
	snapshots, err := t.store.LoadLatestSnapshots()
	if err == nil && len(snapshots) > 0 {
		result["character_snapshots"] = snapshots
		// 同时保留原始设定中的 core/important 角色（快照可能不含新登场角色）
		t.loadFilteredCharacters(result, chapter, warn)
		return
	}
	warn("character_snapshots", err)
	// 无快照时回退到原始设定
	t.loadFilteredCharacters(result, chapter, warn)
}

// writerReferences 返回写作参考资料。章节 1 返回全量，后续章节裁剪掉不再需要的模板。
func (t *ContextTool) writerReferences(chapter int) map[string]string {
	refs := map[string]string{}
	add := func(k, v string) {
		if v != "" {
			refs[k] = v
		}
	}
	// 渐进式加载：始终保留核心参考，前 3 章额外加载完整写作指南
	add("consistency", t.refs.Consistency)
	add("hook_techniques", t.refs.HookTechniques)
	add("quality_checklist", t.refs.QualityChecklist)
	if chapter <= 3 {
		add("chapter_guide", t.refs.ChapterGuide)
		add("dialogue_writing", t.refs.DialogueWriting)
		add("style_reference", t.refs.StyleReference)
	}

	// 仅首章加载的补充参考
	if chapter <= 1 {
		add("chapter_template", t.refs.ChapterTemplate)
		add("content_expansion", t.refs.ContentExpansion)
	}
	return refs
}

func (t *ContextTool) architectReferences() map[string]string {
	refs := map[string]string{}
	add := func(k, v string) {
		if v != "" {
			refs[k] = v
		}
	}
	add("outline_template", t.refs.OutlineTemplate)
	add("character_template", t.refs.CharacterTemplate)
	add("longform_planning", t.refs.LongformPlanning)
	add("differentiation", t.refs.Differentiation)
	add("style_reference", t.refs.StyleReference)
	return refs
}

// foundationStatus 检查基础设定的完备性，返回缺失项列表。
func (t *ContextTool) foundationStatus() map[string]any {
	status := map[string]any{"ready": true}
	var missing []string
	if p, _ := t.store.LoadPremise(); p == "" {
		missing = append(missing, "premise")
	}
	if o, _ := t.store.LoadOutline(); len(o) == 0 {
		missing = append(missing, "outline")
	}
	if c, _ := t.store.LoadCharacters(); len(c) == 0 {
		missing = append(missing, "characters")
	}
	if r, _ := t.store.LoadWorldRules(); len(r) == 0 {
		missing = append(missing, "world_rules")
	}
	if len(missing) > 0 {
		status["ready"] = false
		status["missing"] = missing
	}
	return status
}

// ContextSummary 返回当前状态的简要摘要（供日志使用）。
func (t *ContextTool) ContextSummary() string {
	var parts []string
	if p, _ := t.store.LoadPremise(); p != "" {
		parts = append(parts, "premise:ok")
	}
	if o, _ := t.store.LoadOutline(); o != nil {
		parts = append(parts, fmt.Sprintf("outline:%d chapters", len(o)))
	}
	if c, _ := t.store.LoadCharacters(); c != nil {
		parts = append(parts, fmt.Sprintf("characters:%d", len(c)))
	}
	if len(parts) == 0 {
		return "empty"
	}
	return strings.Join(parts, ", ")
}

// trimByBudget 按优先级裁剪 result，使 JSON 总大小不超过 budget 字节。
// 优先级（从低到高）：references < voice_samples < style_anchors < previous_tail < timeline
//   < recent_state_changes < foreshadow_ledger < relationship_state < 其余（不裁剪）
// 裁剪的 key 会记录到 result["_trimmed"] 供日志排查。
func trimByBudget(result map[string]any, budget int) {
	// 先测量当前大小
	data, err := json.Marshal(result)
	if err != nil || len(data) <= budget {
		return
	}

	// 按优先级从低到高列出可裁剪的 key
	trimOrder := []string{
		"references",
		"voice_samples",
		"style_anchors",
		"previous_tail",
		"timeline",
		"recent_state_changes",
		"foreshadow_ledger",
		"relationship_state",
	}

	var trimmed []string
	for _, key := range trimOrder {
		if _, ok := result[key]; !ok {
			continue
		}
		delete(result, key)
		trimmed = append(trimmed, key)
		data, err = json.Marshal(result)
		if err != nil || len(data) <= budget {
			break
		}
	}
	if len(trimmed) > 0 {
		result["_trimmed"] = trimmed
	}
}
