package promptcompiler

import (
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/desktop/prompts"
)

type EmptyTemplateData struct{}

func validatePromptTemplateSpec(spec PromptBlockSpec) error {
	if strings.TrimSpace(spec.TemplatePath) == "" {
		return fmt.Errorf("registered prompt input requires a template path")
	}
	return nil
}

type promptInputMetadata struct {
	kind PromptInputType
	name string
}

func (v promptInputMetadata) promptInputType() PromptInputType { return v.kind }
func (v promptInputMetadata) promptInputName() string          { return v.name }

type identityPromptInput struct {
	promptInputMetadata
	data IdentityTemplateData
}

func (v identityPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newIdentityPromptInput(data IdentityTemplateData) PromptBlockInput {
	return identityPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputIdentity, name: "IdentityTemplateData"}, data: data}
}

type initialRolePromptInput struct {
	promptInputMetadata
	data InitialRoleTemplateData
}

func (v initialRolePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newInitialRolePromptInput(data InitialRoleTemplateData) PromptBlockInput {
	return initialRolePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputAgentConfig, name: "InitialRoleTemplateData"}, data: data}
}

type emptyPromptInput struct {
	promptInputMetadata
}

func (v emptyPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, EmptyTemplateData{})
}
func newEmptyPromptInput(kind PromptInputType) PromptBlockInput {
	return emptyPromptInput{promptInputMetadata: promptInputMetadata{kind: kind, name: "EmptyTemplateData"}}
}

type platformLoopPromptInput struct {
	promptInputMetadata
	data PlatformLoopTemplateData
}

func (v platformLoopPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newPlatformLoopPromptInput(data PlatformLoopTemplateData) PromptBlockInput {
	return platformLoopPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputSkillPlan, name: "PlatformLoopTemplateData"}, data: data}
}

type agentteamCorePromptInput struct {
	promptInputMetadata
	data AgentTeamCoreTemplateData
}

func (v agentteamCorePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newAgentTeamCorePromptInput(data AgentTeamCoreTemplateData) PromptBlockInput {
	return agentteamCorePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputSkillPlan, name: "AgentTeamCoreTemplateData"}, data: data}
}

type agentteamReferencePromptInput struct {
	promptInputMetadata
	data AgentTeamReferenceTemplateData
}

func (v agentteamReferencePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newLoopReferencePromptInput(data AgentTeamReferenceTemplateData) PromptBlockInput {
	return agentteamReferencePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputSkillPlan, name: "AgentTeamReferenceTemplateData"}, data: data}
}

type execGuidancePromptInput struct {
	promptInputMetadata
	data ExecGuidanceTemplateData
}

func (v execGuidancePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newExecGuidancePromptInput(data ExecGuidanceTemplateData) PromptBlockInput {
	return execGuidancePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputExecGuidance, name: "ExecGuidanceTemplateData"}, data: data}
}

type extensionCatalogGuidancePromptInput struct {
	promptInputMetadata
	data ExtensionCatalogGuidanceTemplateData
}

func (v extensionCatalogGuidancePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newExtensionCatalogGuidancePromptInput(data ExtensionCatalogGuidanceTemplateData) PromptBlockInput {
	return extensionCatalogGuidancePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputExtensionCatalogGuidance, name: "ExtensionCatalogGuidanceTemplateData"}, data: data}
}

type workspaceMemoryPromptInput struct {
	promptInputMetadata
	data WorkspaceMemoryTemplateData
}

func (v workspaceMemoryPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newWorkspaceMemoryPromptInput(data WorkspaceMemoryTemplateData) PromptBlockInput {
	return workspaceMemoryPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputWorkspaceDocument, name: "WorkspaceMemoryTemplateData"}, data: data}
}
func (v workspaceMemoryPromptInput) promptBlockTags() []string {
	if v.data.Remote {
		return []string{"memory:remote"}
	}
	return []string{"memory:workspace"}
}

type workspaceDocumentPromptInput struct {
	promptInputMetadata
	data WorkspaceDocumentTemplateData
}

func (v workspaceDocumentPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newWorkspaceDocumentPromptInput(data WorkspaceDocumentTemplateData) PromptBlockInput {
	return workspaceDocumentPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputWorkspaceDocument, name: "WorkspaceDocumentTemplateData"}, data: data}
}

type workspaceIdentityPromptInput struct {
	promptInputMetadata
	data WorkspaceIdentityTemplateData
}

func (v workspaceIdentityPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newWorkspaceIdentityPromptInput(data WorkspaceIdentityTemplateData) PromptBlockInput {
	return workspaceIdentityPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputWorkspaceDocument, name: "WorkspaceIdentityTemplateData"}, data: data}
}

type oversizePromptInput struct {
	promptInputMetadata
	data WorkspaceDocOversizeTemplateData
}

func (v oversizePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newOversizePromptInput(data WorkspaceDocOversizeTemplateData) PromptBlockInput {
	return oversizePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputWorkspaceDocument, name: "WorkspaceDocOversizeTemplateData"}, data: data}
}

type messagePromptInput struct {
	promptInputMetadata
	data MessageTemplateData
}

func (v messagePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newMessagePromptInput(data MessageTemplateData) PromptBlockInput {
	return messagePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputMessage, name: "MessageTemplateData"}, data: data}
}

type currentMessagePromptInput struct {
	promptInputMetadata
	data CurrentMessageTemplateData
}

func (v currentMessagePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newCurrentMessagePromptInput(data CurrentMessageTemplateData) PromptBlockInput {
	return currentMessagePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputMessage, name: "CurrentMessageTemplateData"}, data: data}
}

type wakeContextPromptInput struct {
	promptInputMetadata
	data WakeContextTemplateData
}

func (v wakeContextPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newWakeContextPromptInput(data WakeContextTemplateData) PromptBlockInput {
	return wakeContextPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputMessage, name: "WakeContextTemplateData"}, data: data}
}

type resumeContextPromptInput struct {
	promptInputMetadata
	data ResumeContextTemplateData
}

func (v resumeContextPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newResumeContextPromptInput(data ResumeContextTemplateData) PromptBlockInput {
	return resumeContextPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputRecovery, name: "ResumeContextTemplateData"}, data: data}
}

type deferredContinuationPromptInput struct {
	promptInputMetadata
	data DeferredContinuationTemplateData
}

func (v deferredContinuationPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newDeferredContinuationPromptInput(data DeferredContinuationTemplateData) PromptBlockInput {
	return deferredContinuationPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputRecovery, name: "DeferredContinuationTemplateData"}, data: data}
}

type unreadSummaryPromptInput struct {
	promptInputMetadata
	data UnreadSummaryTemplateData
}

func (v unreadSummaryPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newUnreadSummaryPromptInput(data UnreadSummaryTemplateData) PromptBlockInput {
	return unreadSummaryPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputMessage, name: "UnreadSummaryTemplateData"}, data: data}
}

type recoveryPromptInput struct {
	promptInputMetadata
	data RecoveryTemplateData
}

func (v recoveryPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newRecoveryPromptInput(data RecoveryTemplateData) PromptBlockInput {
	return recoveryPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputRecovery, name: "RecoveryTemplateData"}, data: data}
}

type recoveryCheckpointPromptInput struct {
	promptInputMetadata
	data RecoveryCheckpointTemplateData
}

func (v recoveryCheckpointPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newRecoveryCheckpointPromptInput(data RecoveryCheckpointTemplateData) PromptBlockInput {
	return recoveryCheckpointPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputRecovery, name: "RecoveryCheckpointTemplateData"}, data: data}
}

type runtimeRetryPromptInput struct {
	promptInputMetadata
	data RuntimeRetryTemplateData
}

func (v runtimeRetryPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newRuntimeRetryPromptInput(data RuntimeRetryTemplateData) PromptBlockInput {
	return runtimeRetryPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputRecovery, name: "RuntimeRetryTemplateData"}, data: data}
}

type finalReplyCheckPromptInput struct {
	promptInputMetadata
	data FinalVisibleReplyCheckTemplateData
}

func (v finalReplyCheckPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newFinalReplyCheckPromptInput(data FinalVisibleReplyCheckTemplateData) PromptBlockInput {
	return finalReplyCheckPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputVisibleReplyCheck, name: "FinalVisibleReplyCheckTemplateData"}, data: data}
}

type workflowEditPromptInput struct {
	promptInputMetadata
	data WorkflowEditPromptData
}

func (v workflowEditPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newWorkflowEditPromptInput(data WorkflowEditPromptData) PromptBlockInput {
	return workflowEditPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputWorkflow, name: "WorkflowEditPromptData"}, data: data}
}

type taskTemplatePromptInput struct {
	promptInputMetadata
	data TaskPromptTemplateData
}

func (v taskTemplatePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newTaskTemplatePromptInput(data TaskPromptTemplateData) PromptBlockInput {
	return taskTemplatePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputTask, name: "TaskPromptTemplateData"}, data: data}
}

type taskScopeContextPromptInput struct {
	promptInputMetadata
	data TaskScopeContextTemplateData
}

func (v taskScopeContextPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newTaskScopeContextPromptInput(data TaskScopeContextTemplateData) PromptBlockInput {
	return taskScopeContextPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputTask, name: "TaskScopeContextTemplateData"}, data: data}
}

type reactionPromptInput struct {
	promptInputMetadata
	data ReactionPromptData
}

func (v reactionPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newReactionPromptInput(data ReactionPromptData) PromptBlockInput {
	return reactionPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputMessage, name: "ReactionPromptData"}, data: data}
}

type messageDetailsPromptInput struct {
	promptInputMetadata
	data MessageDetailsTemplateData
}

func (v messageDetailsPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newMessageDetailsPromptInput(data MessageDetailsTemplateData) PromptBlockInput {
	return messageDetailsPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputMessage, name: "MessageDetailsTemplateData"}, data: data}
}

type deliveryHeaderPromptInput struct {
	promptInputMetadata
	data DeliveryHeaderTemplateData
}

func (v deliveryHeaderPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newDeliveryHeaderPromptInput(data DeliveryHeaderTemplateData) PromptBlockInput {
	return deliveryHeaderPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputMessage, name: "DeliveryHeaderTemplateData"}, data: data}
}

type attachmentPromptInput struct {
	promptInputMetadata
	data AttachmentTemplateData
}

func (v attachmentPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newAttachmentPromptInput(data AttachmentTemplateData) PromptBlockInput {
	return attachmentPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputAttachment, name: "AttachmentTemplateData"}, data: data}
}

type attachmentDetailsPromptInput struct {
	promptInputMetadata
	data AttachmentDetailsTemplateData
}

func (v attachmentDetailsPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newAttachmentDetailsPromptInput(data AttachmentDetailsTemplateData) PromptBlockInput {
	return attachmentDetailsPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputAttachment, name: "AttachmentDetailsTemplateData"}, data: data}
}

type threadRootPromptInput struct {
	promptInputMetadata
	data ThreadRootTemplateData
}

func (v threadRootPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newThreadRootPromptInput(data ThreadRootTemplateData) PromptBlockInput {
	return threadRootPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputMessage, name: "ThreadRootTemplateData"}, data: data}
}

type visibleReplyPromptInput struct {
	promptInputMetadata
	data VisibleReplyContractTemplateData
}

func (v visibleReplyPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newVisibleReplyPromptInput(data VisibleReplyContractTemplateData) PromptBlockInput {
	return visibleReplyPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputVisibleReplyCheck, name: "VisibleReplyContractTemplateData"}, data: data}
}

type replyTargetPromptInput struct {
	promptInputMetadata
	data ReplyTargetTemplateData
}

func (v replyTargetPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newReplyTargetPromptInput(data ReplyTargetTemplateData) PromptBlockInput {
	return replyTargetPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputRenderer, name: "ReplyTargetTemplateData"}, data: data}
}

type attributionPromptInput struct {
	promptInputMetadata
	data AttributionTemplateData
}

func (v attributionPromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	return "", nil
}
func newAttributionPromptInput(data AttributionTemplateData) PromptBlockInput {
	return attributionPromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputRenderer, name: "AttributionTemplateData"}, data: data}
}

type identityNoticePromptInput struct {
	promptInputMetadata
	data IdentityNoticeTemplateData
}

func (v identityNoticePromptInput) renderPromptBlock(spec PromptBlockSpec) (string, error) {
	if err := validatePromptTemplateSpec(spec); err != nil {
		return "", err
	}
	return prompts.Render(spec.TemplatePath, v.data)
}
func newIdentityNoticePromptInput(data IdentityNoticeTemplateData) PromptBlockInput {
	return identityNoticePromptInput{promptInputMetadata: promptInputMetadata{kind: PromptInputIdentity, name: "IdentityNoticeTemplateData"}, data: data}
}
