package run

import (
	"context"
	"time"

	awid "github.com/awebai/aw/awid"
)

type UsageStats struct {
	InputTokens              int
	CacheCreationInputTokens int
	CacheReadInputTokens     int
	OutputTokens             int
}

type RunSummary struct {
	UserPrompt string
	SessionID  string
	AgentText  string
	Failed     bool
}

type ServiceConfig struct {
	Name        string `json:"name"`
	Command     string `json:"command"`
	Description string `json:"description"`
}

func (s UsageStats) TotalInput() int {
	return s.InputTokens + s.CacheCreationInputTokens + s.CacheReadInputTokens
}

type BuildOptions struct {
	SessionID       string
	ContinueSession bool
	AllowedTools    string
	Model           string
	TripOnDanger    bool
	AddDirs         []string
	ImagePaths      []string
	PromptTransport PromptTransport
	ProviderArgs    []string
}

type PromptTransport string

const (
	PromptTransportArg   PromptTransport = "arg"
	PromptTransportStdin PromptTransport = "stdin"
)

type Provider interface {
	Name() string
	BuildCommand(prompt string, opts BuildOptions) ([]string, error)
	BuildResumeCommand(opts BuildOptions) ([]string, error)
	BuildResumeHint(opts BuildOptions) ([]string, error)
	ParseOutput(line string) (*Event, error)
	SessionID(event *Event) string
}

type EventType string

const (
	EventText       EventType = "text"
	EventToolCall   EventType = "tool_call"
	EventToolResult EventType = "tool_result"
	EventDone       EventType = "done"
	EventSystem     EventType = "system"
)

type ToolCall struct {
	Name  string
	Input map[string]any
}

type Event struct {
	Type       EventType
	Text       string
	ToolCalls  []ToolCall
	DurationMS int
	CostUSD    *float64
	Session    string
	IsError    bool
	Usage      *UsageStats
}

type RunPhase string

const (
	RunPhaseIdle             RunPhase = "idle"
	RunPhaseWaitingForPrompt RunPhase = "waiting_for_prompt"
	RunPhaseWaitingForWork   RunPhase = "waiting_for_work"
	RunPhaseWorking          RunPhase = "working"
	RunPhasePaused           RunPhase = "paused"
)

type DisplayKind string

const (
	DisplayKindPlain          DisplayKind = "plain"
	DisplayKindPrompt         DisplayKind = "prompt"
	DisplayKindUserInput      DisplayKind = "user_input"
	DisplayKindAgentText      DisplayKind = "agent_text"
	DisplayKindTool           DisplayKind = "tool"
	DisplayKindToolDetail     DisplayKind = "tool_detail"
	DisplayKindCommunication  DisplayKind = "communication"
	DisplayKindTaskActivity   DisplayKind = "task_activity"
	DisplayKindProviderStdout DisplayKind = "provider_stdout"
	DisplayKindProviderStderr DisplayKind = "provider_stderr"
	DisplayKindDone           DisplayKind = "done"
	DisplayKindInfo           DisplayKind = "info"
	DisplayKindHint           DisplayKind = "hint"
	DisplayKindSeparator      DisplayKind = "separator"
)

type DisplayLine struct {
	Kind DisplayKind
	Text string
}

type ControlEventType string

const (
	DefaultInputPromptLabel = ">> "
	primaryDisplayBullet    = "●"
	primaryBulletPrefix     = primaryDisplayBullet + " "
)

const (
	ControlTypingStarted  ControlEventType = "typing_started"
	ControlBufferUpdated  ControlEventType = "buffer_updated"
	ControlPrompt         ControlEventType = "prompt"
	ControlQuit           ControlEventType = "quit"
	ControlStop           ControlEventType = "stop"
	ControlWait           ControlEventType = "wait"
	ControlResume         ControlEventType = "resume"
	ControlAutofeedOn     ControlEventType = "autofeed_on"
	ControlAutofeedOff    ControlEventType = "autofeed_off"
	ControlProviderInput  ControlEventType = "provider_input"
	ControlStreamError    ControlEventType = "stream_error"
	ControlInterrupt      ControlEventType = "interrupt"
	ControlExitPrompt     ControlEventType = "exit_prompt"
	ControlExitConfirm    ControlEventType = "exit_confirm"
	ControlExitCancel     ControlEventType = "exit_cancel"
	ControlHelp           ControlEventType = "help"
	ControlUnknownCommand ControlEventType = "unknown_command"
)

type ControlEvent struct {
	Type ControlEventType
	Text string
}

type InputController interface {
	Start() error
	Stop() error
	Events() <-chan ControlEvent
	HasPendingInput() bool
}

// UI extends InputController with the optional screen operations the loop uses
// when it is driving an interactive terminal view.
type UI interface {
	InputController
	AppendText(string)
	AppendLine(string)
	SetInputLine(string)
	SetStatusLine(string)
	ClearStatusLine()
	ClearInputLine()
	SetExitConfirmation(bool)
	HasActiveProgram() bool
}

type ServiceSupervisor interface {
	Start(ctx context.Context, services []ServiceConfig, dir string) error
	Stop() error
}

type DispatchDecision struct {
	Mission      string
	CycleContext string
	DisplayLines []DisplayLine
	UserPrompt   string
	ImagePaths   []string
	WaitSeconds  int
	Skip         bool
}

type Dispatcher interface {
	Next(ctx context.Context, autofeed bool, wakeEvent *awid.AgentEvent) (DispatchDecision, error)
}

type CommandRunner func(ctx context.Context, dir string, argv []string, onLine func(string), stderrSink any) error

type SleepFunc func(ctx context.Context, d time.Duration) error

type LoopOptions struct {
	InitialPrompt   string
	BasePrompt      string
	WaitSeconds     int
	IdleWaitSeconds int
	MaxRuns         int
	Autofeed        bool
	ContinueMode    bool
	WorkingDir      string
	AllowedTools    string
	Model           string
	TripOnDanger    bool
	ClaimedTaskRef  string
	ProviderArgs    []string
	ProviderPTY     bool
	Services        []ServiceConfig
}
