package projectmemory

import (
	"sort"
	"strings"

	"github.com/google/uuid"
)

// kindHeadings maps each memory kind to its AGENTS.md section heading.
var kindHeadings = map[string]string{
	KindDecision:   "Decisions",
	KindConvention: "Conventions",
	KindFileMap:    "File Map",
	KindGotcha:     "Gotchas",
}

// agentsMDHeader is the generated-file banner. AGENTS.md is written into the
// worktree before spawn; the banner marks it generated so it is not committed or
// picked up by auto-doc diffs.
const agentsMDHeader = "<!-- GENERATED by AgentCodingWorkflow project memory. Do not edit; changes are overwritten on spawn. -->"

// renderAgentsMD produces deterministic markdown grouped by kind. Within a kind,
// entries are sorted by title then id for stable output. When wsID is set,
// workspace-scoped entries plus project-wide (workspace_id NULL) entries are
// included; otherwise only project-wide entries.
func renderAgentsMD(entries []Entry, wsID *uuid.UUID) string {
	byKind := map[string][]Entry{}
	for _, e := range entries {
		if !includeForWorkspace(e, wsID) {
			continue
		}
		byKind[e.Kind] = append(byKind[e.Kind], e)
	}

	var b strings.Builder
	b.WriteString(agentsMDHeader)
	b.WriteString("\n\n# AGENTS.md\n\n")
	b.WriteString("Project knowledge curated by agents and maintainers. Treat as authoritative context.\n")

	wrote := false
	for _, kind := range validKinds {
		items := byKind[kind]
		if len(items) == 0 {
			continue
		}
		sort.SliceStable(items, func(i, j int) bool {
			if items[i].Title != items[j].Title {
				return items[i].Title < items[j].Title
			}
			return items[i].ID.String() < items[j].ID.String()
		})
		b.WriteString("\n## ")
		b.WriteString(kindHeadings[kind])
		b.WriteString("\n\n")
		for _, e := range items {
			b.WriteString("### ")
			b.WriteString(e.Title)
			b.WriteString("\n")
			if len(e.Tags) > 0 {
				tags := append([]string(nil), e.Tags...)
				sort.Strings(tags)
				b.WriteString("Tags: ")
				b.WriteString(strings.Join(tags, ", "))
				b.WriteString("\n")
			}
			b.WriteString("\n")
			b.WriteString(strings.TrimRight(e.Body, "\n"))
			b.WriteString("\n")
		}
		wrote = true
	}
	if !wrote {
		b.WriteString("\n(No project memory recorded yet.)\n")
	}
	return b.String()
}

// includeForWorkspace decides whether an entry belongs in a worktree's AGENTS.md.
func includeForWorkspace(e Entry, wsID *uuid.UUID) bool {
	if e.WorkspaceID == nil {
		return true // project-wide
	}
	if wsID == nil {
		return false
	}
	return *e.WorkspaceID == *wsID
}
