package npcregistry

import (
	"fmt"
	"io/fs"
	"sync"

	rootassets "gitea.maximumdirect.net/eric/notarius/assets"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/llm"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/promptfs"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/semanticreconcile"
	"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
)

const promptAssetRoot = "assets/prompts"

func promptAssetManifest() (shared.PromptAssetManifest, error) {
	sharedFiles, err := semanticreconcile.SharedPromptFiles()
	if err != nil {
		return shared.PromptAssetManifest{}, fmt.Errorf("load shared semantic reconciliation prompt assets: %w", err)
	}
	return shared.PromptAssetManifest{
		ModuleDir: PromptID,
		ModuleFiles: []promptfs.ModulePromptFile{
			{Name: "prompt.yaml", Path: "prompts/prompt.yaml"},
			{Name: "instructions.md", Path: "prompts/instructions.md"},
		},
		SharedFiles:         []string{"common-dnd-system.md"},
		ExternalSharedFiles: sharedFiles,
	}, nil
}

func moduleAssetFS() (fs.FS, error) {
	assets, err := fs.Sub(rootassets.FS(), "dnd/npc-registry/normalize")
	if err != nil {
		return nil, fmt.Errorf("scope NPC normalization assets: %w", err)
	}
	return assets, nil
}

func RegisterPromptAssets(registry *llm.AssetRegistry) error {
	assets, err := moduleAssetFS()
	if err != nil {
		return err
	}
	manifest, err := promptAssetManifest()
	if err != nil {
		return err
	}
	promptFS, err := manifest.PromptFS(assets)
	if err != nil {
		return fmt.Errorf("prepare NPC normalization prompt assets: %w", err)
	}
	return registry.RegisterPromptFS(promptFS, promptAssetRoot)
}

func promptAssetMetadata() (string, error) {
	promptAssetHashOnce.Do(func() {
		assets, err := moduleAssetFS()
		if err != nil {
			promptAssetHashErr = err
			return
		}
		manifest, err := promptAssetManifest()
		if err != nil {
			promptAssetHashErr = err
			return
		}
		promptAssetHash, promptAssetHashErr = manifest.Hash(assets)
	})
	return promptAssetHash, promptAssetHashErr
}

var (
	promptAssetHashOnce sync.Once
	promptAssetHash     string
	promptAssetHashErr  error
)
