package promptcompiler

import (
	"fmt"
	"strings"
	"time"

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

// RenderOptions reserves future runtime rendering toggles.
type RenderOptions struct{}

// LaunchContractMode selects the runtime's protocol boundary. The compiler
// owns this selection; dispatcher code supplies only the runtime identifier.
type LaunchContractMode string

const (
	LaunchContractCombined LaunchContractMode = "combined"
	LaunchContractSplit    LaunchContractMode = "split"
	LaunchContractNative   LaunchContractMode = "native"
)

// LaunchCompileDescriptor describes one atomic launch compilation. SessionID
// and event facts are inputs to compilation, not pre-rendered prompt text.
type LaunchCompileDescriptor struct {
	EventID               string
	TurnEventType         CompileEventType
	SessionID             string
	Runtime               string
	ContractCarrierFile   string
	ContractMode          LaunchContractMode
	FreshFallbackOnResume bool
}

// LaunchCompileInput contains typed domain input for a launch carrier.
type LaunchCompileInput struct {
	Input CompileInput
}

// CompileDescriptor identifies the runtime input event being compiled.
type CompileDescriptor struct {
	EventID   string           `json:"eventId"`
	EventKind CompileEventKind `json:"eventKind"`
	EventType CompileEventType `json:"eventType"`
	TurnID    string           `json:"turnId,omitempty"`
}

// ConversationBinding carries channel and task routing context into compilation.
type ConversationBinding struct {
	ChannelID        string                 `json:"channelId,omitempty"`
	ChannelType      string                 `json:"channelType,omitempty"`
	TargetID         string                 `json:"targetId,omitempty"`
	ActiveTaskTarget types.ActiveTaskTarget `json:"activeTaskTarget,omitempty,omitzero"`
	WorkflowContext  types.WorkflowContext  `json:"workflowContext,omitempty,omitzero"`
}

type ExecCompileInput struct {
	Enabled  bool
	Guidance ExecGuidanceTemplateData
}

type ExtensionCompileInput struct {
	Enabled  bool
	Guidance ExtensionCatalogGuidanceTemplateData
}

// SkillPlan is the compiler-owned decision for prompt-visible skill slots.
// Slots are ordered and budgeted once; runtime materialization consumes the
// same plan rather than independently inventing prompt order or precedence.
type SkillPlan struct {
	Core             string
	Reference        string
	CoreData         *AgentTeamCoreTemplateData
	ReferenceData    *AgentTeamReferenceTemplateData
	MemorySearchData *MemorySearchGuidanceTemplateData
	OrderedSlots     []SkillPlanSlot
	SourceSlots      []SkillSourceSlot
	BudgetTokens     int
}

// SkillPlanSlot describes one ordered skill source slot.
type SkillPlanSlot struct {
	Name          string
	Priority      int
	Origin        string
	PromptVisible bool
}

// SkillSourceSlot carries the compiler-selected materialization source. The
// runtime uses these priorities verbatim rather than reordering policy.
type SkillSourceSlot struct {
	Dir      string
	Priority int
	Origin   string
}

// AttachmentResolution is the typed result of daemon attachment preparation.
// The compiler renders the user-visible manifest or failure notice; callers
// never append those strings to an already-rendered prompt.
type AttachmentResolution struct {
	Prepared []types.RuntimeAttachment
	Failure  *AttachmentPreparationFailure
}

// AttachmentPreparationFailure contains only trusted preparation facts and a
// bounded operator-facing error string. It is rendered by the attachment
// templates, never interpolated into runtime adapter prose.
type AttachmentPreparationFailure struct {
	Attachments []types.MessageAttachment
	Error       string
}

// AttachmentTemplateItem is the typed data passed to attachment templates.
type AttachmentTemplateItem struct {
	Number      int
	Label       string
	ID          string
	Path        string
	URI         string
	MIME        string
	Size        int64
	ContentType string
}

// AttachmentTemplateData is the complete template input for manifest/failure
// blocks. It is intentionally not a map[string]any.
type AttachmentTemplateData struct {
	Attachments []AttachmentTemplateItem
	Error       string
}

type MessageAttachmentDetailItem struct {
	ID          string
	Filename    string
	ContentType string
	SizeBytes   int64
}

type AttachmentDetailsTemplateData struct {
	Title       string
	ThreadRoot  bool
	Attachments []MessageAttachmentDetailItem
}

type ThreadRootTemplateData struct {
	HeaderParts       string
	MessageID         string
	Timestamp         string
	MessageType       string
	Author            string
	Content           string
	DisplayName       string
	AttachmentDetails string
	EarlierReplyCount int64
}

// DeferredContinuationTemplateData is the typed input for deferred/replay
// guidance.
type DeferredContinuationTemplateData struct {
	Message                   string
	WorkflowContext           string
	Remaining                 int
	MemoryResumeReminder      string
	AgentAuthoredWakeGuidance string
	ReplyToolName             string
	ReplyAuthority            bool
	Reaction                  bool
	TaskScopeDiscussion       bool
	TaskDiscussionDispatch    bool
}

// RecoveryTemplateData is the typed input for recovery continuation templates.
type RecoveryTemplateData struct {
	Text string
}

// RecoveryCheckpointTemplateData is the typed input for lifecycle checkpoint
// wording.
type RecoveryCheckpointTemplateData struct {
	Kind string
}

// RuntimeRetryTemplateData is the typed input for transient retry diagnostics.
type RuntimeRetryTemplateData struct {
	HTTPStatus  int
	Reason      string
	Attempt     int
	MaxAttempts int
	Delay       string
}

// WorkspaceDocConstraint is one measured workspace-document budget overrun.
type WorkspaceDocConstraint struct {
	Actual int
	Limit  int
	Unit   string
}

// WorkspaceDocOversizeTemplateData is the typed input for the oversize notice.
type WorkspaceDocOversizeTemplateData struct {
	DocTitle    string
	SourceID    string
	Path        string
	Constraints []WorkspaceDocConstraint
}

// WorkflowTemplateData is the typed input for workflow callback context.
type WorkflowTemplateData struct {
	Trusted bool
	RunID   string
	StepID  string
}

// TeamPromptTemplateMember is the typed template projection for one Team
// roster member.
type TeamPromptTemplateMember struct {
	Label             string
	Details           string
	ID                string
	Role              string
	Duties            string
	ActorKind         string
	RoleLabel         string
	ActiveParticipant bool
	Self              bool
}

// TeamPromptTemplateContext is the typed template projection for Team context.
type TeamPromptTemplateContext struct {
	Label              string
	ID                 string
	Description        string
	Role               string
	RoleLabel          string
	Overlay            string
	Roster             []TeamPromptTemplateMember
	RosterRemaining    int
	MemberIndex        []string
	MemberIndexMembers []TeamPromptTemplateMember
	Leader             bool
}

// TeamPromptTemplateData is the typed input for Team context guidance.
type TeamPromptTemplateData struct {
	Teams []TeamPromptTemplateContext
}

type WorkflowTeamPromptContext struct {
	Label       string
	ID          string
	MemberID    string
	DisplayName string
	Purpose     string
	RoleLabel   string
	Duty        string
}

type WorkflowTeamPromptData struct {
	Teams []WorkflowTeamPromptContext
}

// TaskReplyTemplateData is the typed input for task reply guidance.
type TaskReplyTemplateData struct {
	Tool           string
	ToolCall       string
	ExactTarget    bool
	TaskDiscussion bool
}

// TaskScopeReplyTemplateData is the typed input for task-scope reply guidance.
type TaskScopeReplyTemplateData struct {
	Tool          string
	TaskScopeCall string
}

type TaskScopeContextTemplateData struct {
	Target           string
	ReplyInstruction string
}

// MessageTemplateData is the typed input for a message header and details.
type MessageDetailsTemplateData struct {
	Details      string
	ThreadRoot   string
	Attachments  string
	TeamContexts string
	Task         string
	WorkflowEdit string
	TaskScope    string
	Reaction     string
}

type MessageTemplateData struct {
	Header      string
	Target      string
	MessageID   string
	Timestamp   string
	AgentType   bool
	Author      string
	Content     string
	DisplayName string
	Details     string
}

// DeliveryReplyTemplateData is the typed input for delivery reply guidance.
type DeliveryReplyTemplateData struct {
	Kind     string
	Target   string
	SendCall string
}

type DeliveryMessageTemplateData struct {
	Body             string
	ReplyInstruction string
	DisplayName      string
	ThreadContext    ThreadContextTemplateData
}

type DeliveryHeaderTemplateData struct {
	Target     string
	MessageID  string
	DeliveryID string
	Source     string
	Timestamp  string
	Type       string
	Author     string
	Payload    string
}

// DeliveryReplayTemplateData is the typed input for deferred delivery context.
type DeliveryReplayTemplateData struct {
	Details string
	State   string
	Reason  string
}

// ReplyTargetTemplateData is the typed input for renderer reply context.
type ReplyTargetTemplateData struct {
	Target   string
	SendCall string
}

// ActiveTaskTemplateData is the typed input for active-task routing guidance.
type ActiveTaskTemplateData struct {
	TaskNumber        int64
	Channel           string
	TaskScope         string
	Source            string
	ThreadTarget      string
	Role              string
	ParentTaskNumber  int64
	RootTaskNumber    int64
	TaskScopeSendCall string
	CheckpointCommand string
}

// ActiveTaskNormalRoutingTemplateData is typed normal message routing input.
type ActiveTaskNormalRoutingTemplateData struct {
	Target          string
	ReadHistoryTool string
	SendMessageTool string
	SendCall        string
}

// AgentAuthoredWakeTemplateData is typed agent-authored wake guidance input.
type AgentAuthoredWakeTemplateData struct{}

// FinalVisibleReplyTarget is one target group in the final-visible-reply
// safety check.
type FinalVisibleReplyTarget struct {
	Target       string
	MessageID    string
	HasTargetKey bool
	Count        int
}

// KimiRestrictedSystemTemplateData is the typed input for Kimi's restricted
// agent system prompt template.
type KimiRestrictedSystemTemplateData struct{}

type VisibleReplyContractTemplateData struct {
	SendMessageTool string
}

// ExecGuidanceAction is one compiler-normalized built-in Exec action fact.
// ExampleJSON is catalog-authored payload; the registered template surrounds
// and labels it rather than treating it as pre-rendered prompt text.
type ExecGuidanceAction struct {
	Domain      string
	Name        string
	ExampleJSON string
}

// ExecGuidanceTemplateData contains typed facts for built-in AgentTeam Exec
// discovery. All AgentTeam-owned wording, punctuation, and iteration live in the
// registered exec guidance template.
type ExecGuidanceTemplateData struct {
	Domains       []string
	CommonActions []ExecGuidanceAction
}

// ExtensionCatalogGuidanceAction is one verified Extension Catalog action
// fact. Names originate in the server-authorized catalog and are rendered only
// inside the registered Extension guidance template.
type ExtensionCatalogGuidanceAction struct {
	ExtensionName string
	ActionName    string
}

// ExtensionCatalogGuidanceTemplateData contains the verified Extension Catalog
// projection used by the persistent runtime guidance block.
type ExtensionCatalogGuidanceTemplateData struct {
	Actions []ExtensionCatalogGuidanceAction
}

func (data ExecGuidanceTemplateData) Empty() bool {
	return len(data.Domains) == 0 && len(data.CommonActions) == 0
}

func (data ExtensionCatalogGuidanceTemplateData) Empty() bool {
	return len(data.Actions) == 0
}

type IdentityTemplateData struct {
	AgentName          string
	ChannelDisplayName string
}

type InitialRoleTemplateData struct {
	Description string
}

type PlatformLoopTemplateData struct {
	WorkStartupStep              string
	ReviewAddTool                string
	ReviewDeleteTool             string
	ReviewListTool               string
	SendMessageTool              string
	ScheduledMessageCreateTool   string
	ScheduledMessageDeleteTool   string
	ScheduledMessagePauseTool    string
	ScheduledMessageResumeTool   string
	ScheduledMessageUpdateTool   string
	ScheduledMessageValidateTool string
}

type WorkspaceMemoryTemplateData struct {
	MemoryIndexPath   string
	MemoryRootAbsPath string
	MemoryRootRelPath string
	Remote            bool
}

type WorkspaceDocumentTemplateData struct {
	Content string
}

type WorkspaceIdentityTemplateData struct {
	Content        string
	AlreadyWrapped bool
}

type AgentTeamCoreTemplateData struct {
	AddReactionTool              string
	CreateTasksTool              string
	GetReactionsTool             string
	ListWorkspaceTool            string
	ListTasksTool                string
	ReadHistoryTool              string
	RemoveReactionTool           string
	ReviewAddTool                string
	ReviewDeleteTool             string
	ReviewListTool               string
	SearchMessagesTool           string
	SearchTasksTool              string
	SendMessageTool              string
	TaskAddCheckpointTool        string
	TaskGetTool                  string
	TaskUpdateTool               string
	ScheduledMessageCreateTool   string
	ScheduledMessageDeleteTool   string
	ScheduledMessageGetTool      string
	ScheduledMessageListTool     string
	ScheduledMessagePauseTool    string
	ScheduledMessageResumeTool   string
	ScheduledMessageRunsTool     string
	ScheduledMessageUpdateTool   string
	ScheduledMessageValidateTool string
	ViewFileTool                 string
}

type AgentTeamReferenceTemplateData = AgentTeamCoreTemplateData

// MemorySearchGuidanceTemplateData is the narrow typed capability fact used by
// the registered AgentTeam Memory guidance block.
type MemorySearchGuidanceTemplateData struct {
	SearchTool string
}

// ExternalSkillPayloadTemplateData is an explicitly named, externally
// authored skill payload. The registered wrapper template labels this payload;
// it is never used as AgentTeam-owned wording or a generic Supplemental channel.
type ExternalSkillPayloadTemplateData struct {
	SkillText string
}

type CurrentMessageTemplateData struct {
	Message                   string
	ActiveTaskTarget          string
	AgentAuthoredWakeGuidance string
}

type ThreadContextTemplateData struct {
	Enabled         bool
	Target          string
	ReadHistoryTool string
}

type WakeContextTemplateData struct {
	Message                   string
	ThreadContext             ThreadContextTemplateData
	ActiveTaskTarget          string
	AgentAuthoredWakeGuidance string
	SendMessageTool           string
	MemoryResumeReminder      string
}

type ResumeContextTemplateData struct {
	Message                   string
	ThreadContext             ThreadContextTemplateData
	ActiveTaskTarget          string
	AgentAuthoredWakeGuidance string
	SendMessageTool           string
	MemoryResumeReminder      string
}

// UnreadSummaryChannel is one normalized unread-count fact. Go may filter
// invalid counts and deterministically order these facts; the template owns
// bullets, labels, punctuation, and singular/plural wording.
type UnreadSummaryChannel struct {
	Channel string
	Count   int
}

type UnreadSummaryTemplateData struct {
	Channels []UnreadSummaryChannel
}

type RecoveryNoticeTemplateData struct {
	Text string
}

type IdentityNoticeTemplateData struct {
	CurrentName string
	OldName     string
}

type ReplyTargetContextTemplateData struct {
	Target   string
	SendCall string
}

type AttributionTemplateData struct {
	TokenEstimate int
}

// FinalVisibleReplyCheckTemplateWake is one typed wake fact rendered by the
// final-visible-reply template.
type FinalVisibleReplyCheckTemplateWake struct {
	Target           string
	MessageID        string
	HasTarget        bool
	IncludeMessageID bool
}

// FinalVisibleReplyCheckTemplateData is the typed template input for the
// final-visible-reply guard.
type FinalVisibleReplyCheckTemplateData struct {
	Wakes           []FinalVisibleReplyCheckTemplateWake
	SendMessageTool string
}

// CompileInput contains all environment and delivery data used by the compiler.
type CompileInput struct {
	AgentID                       string
	AgentName                     string
	AgentDescription              string
	Runtime                       string
	WorkDir                       string
	RestrictedRuntime             bool
	Binding                       ConversationBinding
	Message                       types.InboxMessage
	UnreadSummary                 map[string]int
	ExternalSkillCorePayload      string
	ExternalSkillReferencePayload string
	SkillPlan                     SkillPlan
	Exec                          ExecCompileInput
	Extension                     ExtensionCompileInput
	MemoryResumeReminder          string
	Attachments                   AttachmentResolution
	// PromptFacts is the normalized message/task/workflow/reaction projection
	// used by turn renderers. Raw Inbox metadata is not a render input.
	PromptFacts MessagePromptData
	Delivery    DeliveryCompileInput
}

// DeliveryCompileInput is the source data used to build a delivery envelope.
type DeliveryCompileInput struct {
	MessageID           string
	TargetKey           string
	TargetSeq           int64
	Target              string
	ChannelType         string
	ChannelName         string
	AuthorIdentity      types.AuthorIdentity
	Content             string
	Timestamp           string
	MessageType         string
	Attachments         []types.MessageAttachment
	ResolvedAttachments []types.RuntimeAttachment
	AttachmentFailure   *AttachmentPreparationFailure
	Metadata            map[string]any
	TeamContexts        []types.TeamContext
	WorkflowContext     types.WorkflowContext
	DeliveryMode        string
	RuntimeSessionID    string
	ThreadID            string
	ActiveTurnID        string
	WakeToken           string
	Attempt             int
	DeferredBatchID     string
	ReplayState         string
	DeferredReason      string
	AcceptedAt          time.Time
	OriginalOrderKey    string
	PriorAttemptCount   int
	PendingBehind       int
	EvidenceClass       DeliveryEvidenceClass
	ActiveTaskTarget    types.ActiveTaskTarget
	// PromptFacts are normalized at the compiler input boundary. Metadata is
	// retained only for fingerprints/transport compatibility, never interpreted
	// by renderers.
	PromptFacts MessagePromptData
}

// Policy configures compiler size limits and validation thresholds.
type Policy struct {
	MaxWorkspaceDocBytes     int
	MaxIdentityDocCharacters int
	MaxBlockTokens           int
}

// PromptCompileErrorKind identifies a prompt compiler validation failure class.
type PromptCompileErrorKind string

const (
	ErrWorkspaceDocTooLarge    PromptCompileErrorKind = "workspace_doc_too_large"
	ErrBlockTooLarge           PromptCompileErrorKind = "block_too_large"
	ErrInvalidBlockSemantic    PromptCompileErrorKind = "invalid_block_semantic"
	ErrUnregisteredPromptBlock PromptCompileErrorKind = "unregistered_prompt_block"
	ErrInvalidRuntimeInput     PromptCompileErrorKind = "invalid_runtime_input"
)

// PromptCompileError reports a structured compiler validation or size failure.
type PromptCompileError struct {
	Kind       PromptCompileErrorKind `json:"kind"`
	DocPath    string                 `json:"docPath,omitempty"`
	BlockID    string                 `json:"blockId,omitempty"`
	Bytes      int                    `json:"bytes,omitempty"`
	Characters int                    `json:"characters,omitempty"`
	Limit      int                    `json:"limit,omitempty"`
	Tokens     int                    `json:"tokens,omitempty"`
	Reason     string                 `json:"reason,omitempty"`
	EventID    string                 `json:"eventId"`
	EventType  CompileEventType       `json:"eventType"`
	SourceID   string                 `json:"sourceId,omitempty"`
}

// Error formats the prompt compiler failure for operator-facing diagnostics.
func (e *PromptCompileError) Error() string {
	eventSuffix := ""
	if trimmedType := strings.TrimSpace(string(e.EventType)); trimmedType != "" {
		eventSuffix = " for event " + trimmedType
		if trimmedID := strings.TrimSpace(e.EventID); trimmedID != "" {
			eventSuffix += " (" + trimmedID + ")"
		}
	} else if trimmedID := strings.TrimSpace(e.EventID); trimmedID != "" {
		eventSuffix = " for event " + trimmedID
	}

	sourceSuffix := ""
	if trimmedSource := strings.TrimSpace(e.SourceID); trimmedSource != "" {
		sourceSuffix = fmt.Sprintf(" [source=%s]", trimmedSource)
	}

	switch e.Kind {
	case ErrWorkspaceDocTooLarge:
		if e.Characters > 0 {
			return fmt.Sprintf(
				"prompt compile failed%s: workspace doc %q%s is %d characters, limit %d; shorten the document",
				eventSuffix,
				strings.TrimSpace(e.DocPath),
				sourceSuffix,
				e.Characters,
				e.Limit,
			)
		}
		return fmt.Sprintf(
			"prompt compile failed%s: workspace doc %q%s is %d bytes, limit %d",
			eventSuffix,
			strings.TrimSpace(e.DocPath),
			sourceSuffix,
			e.Bytes,
			e.Limit,
		)
	case ErrBlockTooLarge:
		return fmt.Sprintf(
			"prompt compile failed%s: materialized block %q%s is %d tokens, limit %d",
			eventSuffix,
			strings.TrimSpace(e.BlockID),
			sourceSuffix,
			e.Tokens,
			e.Limit,
		)
	case ErrInvalidBlockSemantic:
		return fmt.Sprintf(
			"prompt compile failed%s: block %q%s has invalid semantics: %s",
			eventSuffix,
			strings.TrimSpace(e.BlockID),
			sourceSuffix,
			strings.TrimSpace(e.Reason),
		)
	case ErrUnregisteredPromptBlock:
		return fmt.Sprintf(
			"prompt compile failed%s: block %q%s is not registered: %s",
			eventSuffix,
			strings.TrimSpace(e.BlockID),
			sourceSuffix,
			strings.TrimSpace(e.Reason),
		)
	case ErrInvalidRuntimeInput:
		return fmt.Sprintf(
			"prompt compile failed%s: runtime input envelope has invalid semantics%s: %s",
			eventSuffix,
			sourceSuffix,
			strings.TrimSpace(e.Reason),
		)
	default:
		return "prompt compile failed" + eventSuffix
	}
}
