package promptcompiler

import (
	"os"
	"path/filepath"
	"strings"

	"github.com/tidbcloud/AgentTeam/desktop/internal/identitydoc"
)

const (
	// localMemoryIndexPath is the root workspace memory index used when no
	// bound Memory repository is available in the workspace.
	localMemoryIndexPath = "MEMORY.md"
	// remoteMemoryRootPath is the workspace-relative mount point for the bound
	// managed Memory repository.
	remoteMemoryRootPath = "memory"
	// remoteMemoryIndexPath is the mounted Memory repository index. When this
	// file exists, the prompt must prefer it for durable memory guidance and
	// keep local state files as runtime recovery only.
	remoteMemoryIndexPath = identitydoc.RemoteMemoryIndexPath
)

// MemoryPrompt describes the workspace memory instructions selected for a
// concrete workdir. Prompt rendering is provider-owned so callers do not need
// to know whether the prompt came from the mounted Memory repository or the
// local fallback layout.
type MemoryPrompt struct {
	Kind         string
	IndexPath    string
	TemplatePath string
	Text         string
}

// MemoryPromptProvider resolves memory instructions for a workspace. Providers
// are tried in order; the first match supplies the prompt text.
type MemoryPromptProvider interface {
	Resolve(workDir string) (MemoryPrompt, bool)
}

type remoteMemoryPromptProvider struct{}
type localMemoryPromptProvider struct{}

func (remoteMemoryPromptProvider) Resolve(workDir string) (MemoryPrompt, bool) {
	if workDir == "" {
		return MemoryPrompt{}, false
	}
	if info, err := os.Stat(filepath.Join(workDir, remoteMemoryIndexPath)); err == nil && !info.IsDir() {
		return MemoryPrompt{
			Kind:         "remote",
			IndexPath:    remoteMemoryIndexPath,
			TemplatePath: templatePlatformRemoteMemory,
			Text:         buildRemoteWorkspaceMemoryText(workDir, remoteMemoryIndexPath),
		}, true
	}
	return MemoryPrompt{}, false
}

func (localMemoryPromptProvider) Resolve(_ string) (MemoryPrompt, bool) {
	return MemoryPrompt{
		Kind:         "local",
		IndexPath:    localMemoryIndexPath,
		TemplatePath: templatePlatformWorkspaceMemory,
		Text:         buildLocalWorkspaceMemoryText(localMemoryIndexPath),
	}, true
}

func resolveMemoryPrompt(workDir string) MemoryPrompt {
	providers := []MemoryPromptProvider{
		remoteMemoryPromptProvider{},
		localMemoryPromptProvider{},
	}
	for _, provider := range providers {
		if prompt, ok := provider.Resolve(workDir); ok {
			return prompt
		}
	}
	return MemoryPrompt{
		Kind:         "local",
		IndexPath:    localMemoryIndexPath,
		TemplatePath: templatePlatformWorkspaceMemory,
		Text:         buildLocalWorkspaceMemoryText(localMemoryIndexPath),
	}
}

func buildLocalWorkspaceMemoryText(memoryIndexPath string) string {
	if memoryIndexPath == "" {
		memoryIndexPath = localMemoryIndexPath
	}
	return renderRegisteredPromptText("platform.workspace_memory", newWorkspaceMemoryPromptInput(WorkspaceMemoryTemplateData{MemoryIndexPath: memoryIndexPath}))
}

func buildRemoteWorkspaceMemoryText(workDir, memoryIndexPath string) string {
	if memoryIndexPath == "" {
		memoryIndexPath = remoteMemoryIndexPath
	}
	return renderRegisteredPromptText("platform.workspace_memory", newWorkspaceMemoryPromptInput(WorkspaceMemoryTemplateData{MemoryIndexPath: memoryIndexPath, MemoryRootAbsPath: remoteMemoryRootDisplayPath(workDir), MemoryRootRelPath: remoteMemoryRootPath + "/", Remote: true}))
}

func remoteMemoryRootDisplayPath(workDir string) string {
	workDir = strings.TrimSpace(workDir)
	if workDir == "" {
		return remoteMemoryRootPath
	}
	rootPath := filepath.Join(workDir, remoteMemoryRootPath)
	if absPath, err := filepath.Abs(rootPath); err == nil {
		return absPath
	}
	return filepath.Clean(rootPath)
}

func buildAgentIdentityText() string {
	return renderRegisteredPromptText("platform.agent_identity", newEmptyPromptInput(PromptInputIdentity))
}

func buildIdentityDocText(content string) string {
	content = strings.TrimSpace(content)
	if content == "" {
		return ""
	}
	return renderRegisteredPromptText("workspace.identity", newWorkspaceIdentityPromptInput(WorkspaceIdentityTemplateData{Content: content}))
}
