package ui

import (
	"time"
)

// State represents the current UI state.
type State int

const (
	StateInput State = iota
	StateProcessing
	StateStreaming
	StatePermissionPrompt
	StateQuestionPrompt
	StatePlanApproval
	StateModelSelector
	StateShortcutsOverlay
	StateCommandPalette
	StateDiffPreview
	StateMultiDiffPreview
	StateSearchResults
	StateGitStatus
	StateFileBrowser
	StateBatchProgress
	StateContextObservatory
	StateFilePeek
)

// typeAheadActive reports whether the main input should receive keystrokes
// and be rendered: normal input state, plus processing/streaming for
// type-ahead composition (Enter then queues). Modals always win.
func (m *Model) typeAheadActive() bool {
	if m.isModalState() {
		return false
	}
	return m.state == StateInput || m.state == StateProcessing || m.state == StateStreaming
}

// isModalState returns true if the current state is a modal overlay
// where the main input should not receive events.
func (m *Model) isModalState() bool {
	switch m.state {
	case StatePermissionPrompt, StateQuestionPrompt, StatePlanApproval,
		StateModelSelector, StateShortcutsOverlay, StateCommandPalette,
		StateDiffPreview, StateMultiDiffPreview, StateSearchResults, StateGitStatus,
		StateFileBrowser, StateBatchProgress, StateContextObservatory:
		return true
	}
	return false
}

// StatusBarLayout determines the level of detail shown in the status bar based on terminal width.
type StatusBarLayout int

const (
	StatusBarLayoutFull    StatusBarLayout = iota // >= 120 chars: full information
	StatusBarLayoutMedium                         // 80-119 chars: shortened paths
	StatusBarLayoutCompact                        // 60-79 chars: key elements only
	StatusBarLayoutMinimal                        // < 60 chars: icons + token bar only
)

// ModelInfo contains information about an available model.
type ModelInfo struct {
	ID          string
	Name        string
	Description string
}

// PermissionDecision represents the user's permission choice.
type PermissionDecision int

const (
	PermissionAllow PermissionDecision = iota
	PermissionAllowSession
	PermissionDeny
	PermissionDenySession
)

// PlanApprovalDecision represents the user's decision on a plan.
type PlanApprovalDecision int

const (
	PlanApproved PlanApprovalDecision = iota
	PlanRejected
	PlanModifyRequested
)

// Message types for communication.
type (
	StreamTextMsg     string
	StreamThinkingMsg string
	// QueuedCountMsg carries the current type-ahead queue length (sent on
	// every enqueue/dequeue) for the status-bar badge.
	QueuedCountMsg int
	ToolCallMsg    struct {
		Name string
		Args map[string]any
	}
	ToolResultMsg struct {
		Name    string
		Args    map[string]any
		Content string
		Failed  bool
		Error   string
	}
	// ToolProgressMsg is sent periodically during long-running tool execution.
	ToolProgressMsg struct {
		Name           string
		Elapsed        time.Duration
		Progress       float64 // 0.0-1.0, -1 for indeterminate
		CurrentStep    string  // "Copying files...", "Reading..."
		TotalBytes     int64
		ProcessedBytes int64
		Cancellable    bool
	}
	ResponseDoneMsg struct{}
	// ThinkingTickMsg signals that the model is actively thinking/reasoning.
	// Used to keep the UI alive and update elapsed time during extended thinking.
	ThinkingTickMsg struct{}
	// ResponseMetadataMsg carries metadata about the completed response.
	ResponseMetadataMsg struct {
		Model                string
		InputTokens          int
		OutputTokens         int
		CacheReadInputTokens int
		Duration             time.Duration
		ToolsUsed            []string
		Cost                 float64 // Estimated cost in USD (0 = unknown)
	}
	ErrorMsg      error
	TodoUpdateMsg []string
	// LoopIterationMsg carries executor loop iteration progress.
	LoopIterationMsg struct {
		Iteration int
		ToolsUsed int
	}
	// StreamTokenUpdateMsg is sent during streaming to update token estimates.
	StreamTokenUpdateMsg struct {
		EstimatedOutputTokens int
	}

	TokenUsageMsg struct {
		Tokens       int
		OutputTokens int // Tokens generated in the current response (streaming estimate)
		MaxTokens    int
		PercentUsed  float64
		NearLimit    bool
		IsEstimate   bool // True when token count is an estimate (API call failed)
	}
	ProjectInfoMsg struct {
		ProjectType string
		ProjectName string
	}
	// PermissionRequestMsg requests user permission for a tool.
	PermissionRequestMsg struct {
		ToolName  string
		Args      map[string]any
		RiskLevel string
		Reason    string
	}
	// PermissionResponseMsg carries the user's permission decision.
	PermissionResponseMsg struct {
		Decision PermissionDecision
	}
	// QuestionRequestMsg requests user input for a question.
	QuestionRequestMsg struct {
		Question string
		Options  []string
		Default  string
	}
	// QuestionResponseMsg carries the user's answer.
	QuestionResponseMsg struct {
		Answer string
	}
	// PlanApprovalRequestMsg requests approval for a plan.
	PlanApprovalRequestMsg struct {
		Title       string
		Description string
		Steps       []PlanStepInfo
		// Contract fields (optional, shown when ContractName is non-empty)
		ContractName string
		Intent       string
		Boundaries   []string // Pre-formatted
		Invariants   []string
		Examples     []string
	}
	// PlanStepInfo contains info about a plan step for display.
	PlanStepInfo struct {
		ID          int
		Title       string
		Description string
	}
	// PlanProgressMsg updates plan execution progress.
	PlanProgressMsg struct {
		PlanID        string
		CurrentStepID int
		CurrentTitle  string
		TotalSteps    int
		Completed     int
		Progress      float64 // 0.0 to 1.0
		Status        string  // "in_progress", "completed", "failed"
		SubStepInfo   string  // Sub-agent progress detail
		Reason        string  // Transition reason (pause/fail/skip/completion context)
	}
	// PlanCompleteMsg indicates a plan execution is complete.
	PlanCompleteMsg struct {
		PlanID   string
		Success  bool
		Duration time.Duration
	}
	// ConfigUpdateMsg signals that config has changed and UI should refresh.
	ConfigUpdateMsg struct {
		PermissionsEnabled  bool
		SandboxEnabled      bool
		PlanningModeEnabled bool
		ModelName           string // Current model name (empty = no change)
	}
	// BackgroundTaskMsg signals a background task state change.
	BackgroundTaskMsg struct {
		ID          string // Task/agent ID
		Type        string // "agent" or "shell"
		Description string // Short description of the task
		Status      string // "running", "completed", "failed", "cancelled"

		// Phase 2: Progress tracking fields
		Progress      float64       // 0.0 to 1.0
		CurrentStep   int           // Current step number
		TotalSteps    int           // Total expected steps
		CurrentAction string        // "Reading file...", "Searching..."
		ToolsUsed     []string      // List of tools used so far
		TokensUsed    int           // Approximate tokens consumed
		Elapsed       time.Duration // Time elapsed since start
	}

	// BackgroundTaskProgressMsg provides periodic progress updates for background tasks.
	BackgroundTaskProgressMsg struct {
		ID            string        // Task/agent ID
		Progress      float64       // 0.0 to 1.0
		CurrentStep   int           // Current step number
		TotalSteps    int           // Total expected steps
		CurrentAction string        // Current action description
		ToolsUsed     []string      // Tools used so far
		Elapsed       time.Duration // Time elapsed
	}

	// SubAgentActivityMsg reports activity from sub-agents.
	//
	// Task is populated only on Status=="start" — it carries the prompt the
	// sub-agent was dispatched with, so the activity feed can display what
	// each agent is actually working on instead of a generic "Sub-agent: X".
	// For tool-level events the UI already has the task from the start event.
	SubAgentActivityMsg struct {
		AgentID   string
		AgentType string
		Task      string // Dispatch prompt, filled only on Status=="start"
		ToolName  string
		ToolArgs  map[string]any
		Status    string        // "start", "tool_start", "tool_end", "complete", "failed"
		Elapsed   time.Duration // Time elapsed since agent start
	}

	// InlineDiffMsg carries a compact diff for display in the output stream.
	InlineDiffMsg struct {
		FilePath string
		OldText  string
		NewText  string
	}

	// AgentTreeUpdateMsg carries a snapshot of the coordinated agent tree.
	AgentTreeUpdateMsg struct {
		Nodes []AgentTreeNode
	}

	// LearningInsightMsg carries a learning insight for display as a toast.
	LearningInsightMsg struct {
		Message string
	}

	// ContextHealthMsg delivers detailed context health data for the observatory.
	ContextHealthMsg struct {
		TotalTokens       int
		MaxTokens         int
		PercentUsed       float64
		SystemTokens      int
		InstructionTokens int
		HistoryTokens     int
		ToolTokens        int
		ActiveFiles       []string // List of files currently in context
		LastPruningTime   time.Time
		PruningAlert      string // Current pruning status message

		// Rate limit metadata for observatory
		RequestsRemaining int64
		RequestsLimit     int64
		RequestsReset     time.Duration
		TokensRemaining   int64
		TokensLimit       int64
		TokensReset       time.Duration
	}

	// FilePeekMsg delivers a snippet of a file for transient "peeking".
	FilePeekMsg struct {
		FilePath string
		Title    string
		Content  string // Markdown or plaintext
		Action   string // "reading", "modifying", "created"
	}
)

// ActivityType distinguishes sources of activity.
type ActivityType int

const (
	ActivityTypeTool ActivityType = iota
	ActivityTypeAgent
	ActivityTypeSystem
)

// ActivityStatus tracks the lifecycle of an activity entry.
type ActivityStatus int

const (
	ActivityPending ActivityStatus = iota
	ActivityRunning
	ActivityCompleted
	ActivityFailed
)

// ActivityFeedEntry represents an entry in the activity feed.
type ActivityFeedEntry struct {
	ID            string
	Type          ActivityType
	Name          string // Tool or agent name
	Description   string // "Reading /path/to/file.go"
	Status        ActivityStatus
	StartTime     time.Time
	Duration      time.Duration
	AgentID       string         // For sub-agent tool calls
	Details       map[string]any // Additional details
	ResultSummary string         // Brief summary of result (e.g. "42 files", "150 lines")
}

// StatusType indicates the type of status update.
type StatusType int

const (
	StatusRetry StatusType = iota
	StatusRateLimit
	StatusStreamIdle
	StatusStreamResume
	StatusRecoverableError
	StatusCancelled
	StatusWarning
	StatusInfo
	StatusThinkingIdle
)

// StatusUpdateMsg carries status updates from clients to the UI.
// Used to show feedback during retry operations, rate limiting, and stream idle states.
type StatusUpdateMsg struct {
	Type    StatusType
	Message string
	Details map[string]any
}

// PlanningModeToggledMsg is sent after async toggle completes.
type PlanningModeToggledMsg struct {
	Enabled bool
}

// SessionModeCycledMsg is sent after Shift+Tab cycles the canonical
// session mode (Normal → Plan → YOLO → Normal). Mode is the lowercase
// name of the NEW state ("normal", "plan", "yolo") so the TUI can emit
// a toast + update the status bar without knowing the app-level enum.
type SessionModeCycledMsg struct {
	Mode string
}

// RuntimeStatusSnapshot is a compact runtime health snapshot for Status Bar 2.0.
type RuntimeStatusSnapshot struct {
	Mode               string
	Provider           string
	RequestBreaker     string
	StepBreaker        string
	HeartbeatAge       time.Duration
	HasHeartbeat       bool
	DegradedRemaining  time.Duration
	ConsecutiveFailure int
}

// RuntimeStatusMsg delivers a runtime status snapshot fetched in the background.
type RuntimeStatusMsg struct {
	Status RuntimeStatusSnapshot
}
