package prompt

import (
	"embed"
	"strings"
	"sync"
)

//go:embed files
var files embed.FS

const (
	fileOverlay                    = "files/overlay.md"
	fileStyle8DSystem              = "files/style8d.system.md"
	fileStyle8DSchema              = "files/style8d.schema.md"
	fileAIChatSystem               = "files/ai.chat.system.md"
	fileIslanderSystem             = "files/ai.islander.system.md"
	fileKnowledgeGraphSystem       = "files/knowledge_graph.system.md"
	fileKnowledgeGraphLLMSystem    = "files/knowledge_graph_llm.system.md"
	fileKnowledgeGraphUser         = "files/knowledge_graph.user.md"
	fileKnowledgeGraphLLMUser      = "files/knowledge_graph_llm.user.md"
	fileKnowledgeGraphSupplemental = "files/knowledge_graph.supplemental.md"
	fileKnowledgeGraphQueries      = "files/knowledge_graph.queries.json"
	fileOutreachPlacementSystem    = "files/outreach_placement.system.md"
	fileOutreachPlacementUser      = "files/outreach_placement.user.md"
	fileMatrixPlacementSystem      = "files/matrix_placement.system.md"
	fileMatrixPlacementUser        = "files/matrix_placement.user.md"
	fileMatrixCopySystem           = "files/matrix_copy.system.md"
	fileMatrixCopyUser             = "files/matrix_copy.user.md"
)

// Keys identify prompt slots loaded from internal/library/prompt/files/*.md.
const (
	KeyStyle8DSystem              = "style8d.system"
	KeyStyle8DSchema              = "style8d.schema"
	KeyAIChatSystem               = "ai.chat.system"
	KeyIslanderSystem             = "ai.islander.system"
	KeyKnowledgeGraphSystem       = "knowledge_graph.system"
	KeyKnowledgeGraphLLMSystem    = "knowledge_graph_llm.system"
	KeyKnowledgeGraphUser         = "knowledge_graph.user"
	KeyKnowledgeGraphLLMUser      = "knowledge_graph_llm.user"
	KeyKnowledgeGraphSupplemental = "knowledge_graph.supplemental"
	KeyKnowledgeGraphQueries      = "knowledge_graph.queries"
	KeyOutreachPlacementSystem    = "outreach_placement.system"
	KeyOutreachPlacementUser      = "outreach_placement.user"
	KeyMatrixPlacementSystem      = "matrix_placement.system"
	KeyMatrixPlacementUser        = "matrix_placement.user"
	KeyMatrixCopySystem           = "matrix_copy.system"
	KeyMatrixCopyUser             = "matrix_copy.user"
)

var slotFiles = map[string]string{
	KeyStyle8DSystem:              fileStyle8DSystem,
	KeyStyle8DSchema:              fileStyle8DSchema,
	KeyAIChatSystem:               fileAIChatSystem,
	KeyIslanderSystem:             fileIslanderSystem,
	KeyKnowledgeGraphSystem:       fileKnowledgeGraphSystem,
	KeyKnowledgeGraphLLMSystem:    fileKnowledgeGraphLLMSystem,
	KeyKnowledgeGraphUser:         fileKnowledgeGraphUser,
	KeyKnowledgeGraphLLMUser:      fileKnowledgeGraphLLMUser,
	KeyKnowledgeGraphSupplemental: fileKnowledgeGraphSupplemental,
	KeyOutreachPlacementSystem:    fileOutreachPlacementSystem,
	KeyOutreachPlacementUser:      fileOutreachPlacementUser,
	KeyMatrixPlacementSystem:      fileMatrixPlacementSystem,
	KeyMatrixPlacementUser:        fileMatrixPlacementUser,
	KeyMatrixCopySystem:           fileMatrixCopySystem,
	KeyMatrixCopyUser:             fileMatrixCopyUser,
}

var (
	loadOnce  sync.Once
	loadErr   error
	overlay   string
	slotTexts map[string]string
)

func initRegistry() {
	overlay, loadErr = readFile(fileOverlay)
	if loadErr != nil {
		return
	}
	slotTexts = make(map[string]string, len(slotFiles))
	for key, path := range slotFiles {
		text, err := readFile(path)
		if err != nil {
			loadErr = err
			return
		}
		slotTexts[key] = text
	}
}

func readFile(path string) (string, error) {
	raw, err := files.ReadFile(path)
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(string(raw)), nil
}

func ensureLoaded() error {
	loadOnce.Do(initRegistry)
	return loadErr
}

// Overlay returns the global prepend text (Agents.md style).
func Overlay() (string, error) {
	if err := ensureLoaded(); err != nil {
		return "", err
	}
	return overlay, nil
}

// Slot returns one configured prompt body.
func Slot(key string) (string, error) {
	if err := ensureLoaded(); err != nil {
		return "", err
	}
	text, ok := slotTexts[key]
	if !ok {
		return "", ErrUnknownKey(key)
	}
	return text, nil
}

// KnownKey reports whether key is registered.
func KnownKey(key string) bool {
	_, ok := slotFiles[key]
	return ok
}
