package service

import (
	"sort"
	"time"

	memorymodel "github.com/LoveLosita/smartflow/backend/memory/model"
)

// RankItems 对读取结果做统一重排。
//
// 步骤化说明：
// 1. 先基于 importance / confidence / recency 构造基础分，保持和旧链路相近的排序直觉；
// 2. 再叠加“显式记忆 / 类型优先级”奖励，让 constraint 与 preference 更稳定地排在前面；
// 3. 同分按 ID 降序，保证排序在日志与测试里具备稳定性。
func RankItems(items []memorymodel.ItemDTO, now time.Time) []memorymodel.ItemDTO {
	if len(items) == 0 {
		return nil
	}

	ranked := make([]memorymodel.ItemDTO, len(items))
	copy(ranked, items)
	sort.SliceStable(ranked, func(i, j int) bool {
		left := scoreRankedItem(ranked[i], now)
		right := scoreRankedItem(ranked[j], now)
		if left == right {
			return ranked[i].ID > ranked[j].ID
		}
		return left > right
	})
	return ranked
}

// scoreRankedItem 计算 hybrid 读链路的统一重排分数。
//
// 说明：
// 1. 这里仍然只依赖条目自身属性，不引入 conversation_id 加分；
// 2. 原因是同对话内容本就已经存在于上下文窗口，记忆读侧应专注跨对话补充；
// 3. 类型加权仍然保留，用于确保 constraint / preference 的业务优先级稳定生效。
func scoreRankedItem(item memorymodel.ItemDTO, now time.Time) float64 {
	score := 0.35*clamp01(item.Importance) + 0.3*clamp01(item.Confidence) + 0.2*recencyScoreDTO(item, now)
	if item.IsExplicit {
		score += 0.1
	}
	switch memorymodel.NormalizeMemoryType(item.MemoryType) {
	case memorymodel.MemoryTypeConstraint:
		score += 0.15
	case memorymodel.MemoryTypePreference:
		score += 0.10
	}
	return score
}

func recencyScoreDTO(item memorymodel.ItemDTO, now time.Time) float64 {
	base := item.UpdatedAt
	if base == nil {
		base = item.CreatedAt
	}
	if base == nil || now.Before(*base) {
		return 0.5
	}

	age := now.Sub(*base)
	switch {
	case age <= 24*time.Hour:
		return 1
	case age <= 7*24*time.Hour:
		return 0.85
	case age <= 30*24*time.Hour:
		return 0.65
	case age <= 90*24*time.Hour:
		return 0.45
	default:
		return 0.25
	}
}
