package dto

import (
	"encoding/json"
	"time"
)

// WorkflowRunCancelActionRequest carries caller-authored audit context. Actor
// identity is never accepted from JSON; the authenticated human or Agent
// transport injects it into the cancellation command.
type WorkflowRunCancelActionRequest struct {
	Reason string `json:"reason,omitempty"`
}

// WorkflowRunResponse intentionally omits the frozen execution-owner
// snapshot, runtime scheduling cursor, idempotency receipts, and all leases.
// Payload fields are present on detail/control responses and omitted from list
// summaries.
type WorkflowRunResponse struct {
	ID                 string          `json:"id"`
	InvocationID       string          `json:"invocationId"`
	PlanID             string          `json:"planId"`
	PlanKey            string          `json:"planKey,omitempty"`
	PlanDisplayName    string          `json:"planDisplayName,omitempty"`
	BindingID          string          `json:"bindingId,omitempty"`
	BindingKey         string          `json:"bindingKey,omitempty"`
	BindingDisplayName string          `json:"bindingDisplayName,omitempty"`
	PlanVersionID      string          `json:"planVersionId"`
	Status             string          `json:"status"`
	Input              json.RawMessage `json:"input,omitempty"`
	State              json.RawMessage `json:"state,omitempty"`
	Output             json.RawMessage `json:"output,omitempty"`
	ErrorCode          string          `json:"errorCode,omitempty"`
	Error              json.RawMessage `json:"error,omitempty"`
	QueuedAt           time.Time       `json:"queuedAt"`
	StartedAt          *time.Time      `json:"startedAt,omitempty"`
	CompletedAt        *time.Time      `json:"completedAt,omitempty"`
	CanceledAt         *time.Time      `json:"canceledAt,omitempty"`
	Revision           int64           `json:"revision"`
	CreatedAt          time.Time       `json:"createdAt"`
	UpdatedAt          time.Time       `json:"updatedAt"`
}

type WorkflowRunListResponse struct {
	Items      []WorkflowRunResponse `json:"items"`
	NextCursor string                `json:"nextCursor,omitempty"`
}

// WorkflowCalendarResponse is a complete, bounded half-open time window. It
// mixes accepted Runs with projected occurrences that have not created a Run.
type WorkflowCalendarResponse struct {
	From  time.Time              `json:"from"`
	To    time.Time              `json:"to"`
	Items []WorkflowCalendarItem `json:"items"`
}

type WorkflowCalendarItem struct {
	Kind     string                    `json:"kind"`
	OccursAt time.Time                 `json:"occursAt"`
	Workflow WorkflowCalendarWorkflow  `json:"workflow"`
	Schedule *WorkflowCalendarSchedule `json:"schedule,omitempty"`
	Run      *WorkflowCalendarRun      `json:"run,omitempty"`
}

type WorkflowCalendarWorkflow struct {
	PlanID        string `json:"planId"`
	PlanVersionID string `json:"planVersionId"`
	Key           string `json:"key,omitempty"`
	DisplayName   string `json:"displayName"`
}

type WorkflowCalendarSchedule struct {
	BindingID          string `json:"bindingId"`
	BindingRevisionID  string `json:"bindingRevisionId"`
	BindingSourceID    string `json:"bindingSourceId"`
	BindingKey         string `json:"bindingKey,omitempty"`
	BindingDisplayName string `json:"bindingDisplayName"`
	OccurrenceKey      string `json:"occurrenceKey"`
}

type WorkflowCalendarRun struct {
	ID           string     `json:"id"`
	InvocationID string     `json:"invocationId"`
	Status       string     `json:"status"`
	QueuedAt     time.Time  `json:"queuedAt"`
	StartedAt    *time.Time `json:"startedAt,omitempty"`
	CompletedAt  *time.Time `json:"completedAt,omitempty"`
	CanceledAt   *time.Time `json:"canceledAt,omitempty"`
}

type WorkflowRunStepResponse struct {
	StepID     string          `json:"stepId"`
	Type       string          `json:"type"`
	Status     string          `json:"status"`
	Attempt    int64           `json:"attempt"`
	DeadlineAt *time.Time      `json:"deadlineAt,omitempty"`
	ErrorCode  string          `json:"errorCode,omitempty"`
	Error      json.RawMessage `json:"error,omitempty"`
}

type WorkflowRunWaitingResponse struct {
	Kind string `json:"kind"`
	// Reason is a stable machine-readable explanation for the waiting kind.
	// responder_capacity never identifies a candidate Agent or pool.
	Reason     string     `json:"reason,omitempty"`
	StepID     string     `json:"stepId,omitempty"`
	DeadlineAt *time.Time `json:"deadlineAt,omitempty"`
}

type WorkflowRunShowResponse struct {
	Run         WorkflowRunResponse         `json:"run"`
	CurrentStep *WorkflowRunStepResponse    `json:"currentStep,omitempty"`
	WaitingOn   *WorkflowRunWaitingResponse `json:"waitingOn,omitempty"`
}

type WorkflowRunLogEntryResponse struct {
	Sequence int64           `json:"sequence"`
	Time     time.Time       `json:"time"`
	Level    string          `json:"level"`
	Kind     string          `json:"kind"`
	StepID   string          `json:"stepId,omitempty"`
	Message  string          `json:"message"`
	Details  json.RawMessage `json:"details,omitempty"`
}

type WorkflowRunLogsResponse struct {
	Items      []WorkflowRunLogEntryResponse `json:"items"`
	NextCursor string                        `json:"nextCursor,omitempty"`
}

type WorkflowRunActivationResponse struct {
	ID                 string          `json:"id"`
	RunID              string          `json:"runId"`
	LogicalKey         string          `json:"logicalKey"`
	ParentActivationID string          `json:"parentActivationId,omitempty"`
	NodeID             string          `json:"nodeId"`
	Opcode             string          `json:"opcode"`
	Status             string          `json:"status"`
	Input              json.RawMessage `json:"input"`
	Output             json.RawMessage `json:"output,omitempty"`
	ScopeContext       json.RawMessage `json:"scopeContext"`
	SelectedPort       string          `json:"selectedPort,omitempty"`
	AttemptCount       int64           `json:"attemptCount"`
	RetryAt            *time.Time      `json:"retryAt,omitempty"`
	WakeAt             *time.Time      `json:"wakeAt,omitempty"`
	DeadlineAt         *time.Time      `json:"deadlineAt,omitempty"`
	ErrorCode          string          `json:"errorCode,omitempty"`
	Error              json.RawMessage `json:"error,omitempty"`
	StartedAt          *time.Time      `json:"startedAt,omitempty"`
	CompletedAt        *time.Time      `json:"completedAt,omitempty"`
	CreatedAt          time.Time       `json:"createdAt"`
	UpdatedAt          time.Time       `json:"updatedAt"`
}

type WorkflowRunActivationListResponse struct {
	Items      []WorkflowRunActivationResponse `json:"items"`
	NextCursor string                          `json:"nextCursor,omitempty"`
}

// WorkflowRunEffectResponse is an observable receipt, not a dispatch
// command. Request is a redacted view suitable for graph/timeline inspection;
// semantic idempotency keys, frozen execution identity, client replay keys,
// and lease fences are deliberately absent.
type WorkflowRunEffectResponse struct {
	ID           string          `json:"id"`
	RunID        string          `json:"runId"`
	ActivationID string          `json:"activationId"`
	Kind         string          `json:"kind"`
	Status       string          `json:"status"`
	Request      json.RawMessage `json:"request,omitempty"`
	Result       json.RawMessage `json:"result,omitempty"`
	AttemptCount int64           `json:"attemptCount"`
	RetryAt      *time.Time      `json:"retryAt,omitempty"`
	DeadlineAt   *time.Time      `json:"deadlineAt,omitempty"`
	ErrorCode    string          `json:"errorCode,omitempty"`
	Error        json.RawMessage `json:"error,omitempty"`
	DeliveredAt  *time.Time      `json:"deliveredAt,omitempty"`
	CompletedAt  *time.Time      `json:"completedAt,omitempty"`
	QueuedAt     *time.Time      `json:"queuedAt,omitempty"`
	// WaitingReason is populated only for the canonical waiting_for_responder
	// status and is deliberately independent of candidate identity.
	WaitingReason string    `json:"waitingReason,omitempty"`
	CreatedAt     time.Time `json:"createdAt"`
	UpdatedAt     time.Time `json:"updatedAt"`
	// CallbackResponderAgentID is the frozen canonical callback Agent. The UI
	// hydrates the display name from the workspace Agent directory and falls
	// back to "@<agentId>".
	CallbackResponderAgentID string `json:"callbackResponderAgentId,omitempty"`
	// QueueStatus is the FIFO phase of a callback effect: queued, dispatching,
	// completed, or canceled. Empty for effects that were never queued.
	QueueStatus string `json:"queueStatus,omitempty"`
	// AheadCount is the number of earlier callbacks still active ahead of this
	// one for the same (workspace, Agent).
	AheadCount int64 `json:"aheadCount,omitempty"`
	// QueuePosition is AheadCount + 1 while queued.
	QueuePosition int64 `json:"queuePosition,omitempty"`
	// OwnerRunID/OwnerNodeID/OwnerEffectID identify the current execution-lease
	// owner when this effect does not hold it, so the UI can show who is ahead.
	OwnerRunID    string `json:"ownerRunId,omitempty"`
	OwnerNodeID   string `json:"ownerNodeId,omitempty"`
	OwnerEffectID string `json:"ownerEffectId,omitempty"`
	IsLeaseOwner  bool   `json:"isLeaseOwner,omitempty"`
	// RecoveryAttemptCount is the monotonic lifetime history of automatic
	// recovery sends already made for this callback. It is retained across
	// Agent recovery resets and park/epoch transitions.
	RecoveryAttemptCount int `json:"recoveryAttemptCount,omitempty"`
	// RecoveryPausedAt is set by the non-terminal `pause` action; while present,
	// automatic recovery is stopped permanently for the awaiting callback.
	RecoveryPausedAt *time.Time `json:"recoveryPausedAt,omitempty"`
	// ParkState is the durable park FSM state ("" none, "arm_on_idle", "parked")
	// set by the non-terminal `park` action.
	ParkState string `json:"parkState,omitempty"`
}

type WorkflowRunEffectListResponse struct {
	Items      []WorkflowRunEffectResponse `json:"items"`
	NextCursor string                      `json:"nextCursor,omitempty"`
}

type WorkflowRunEventResponse struct {
	ID        string          `json:"id"`
	RunID     string          `json:"runId"`
	Sequence  int64           `json:"sequence"`
	Type      string          `json:"type"`
	Payload   json.RawMessage `json:"payload"`
	CreatedAt time.Time       `json:"createdAt"`
}

type WorkflowRunEventListResponse struct {
	Items      []WorkflowRunEventResponse `json:"items"`
	NextCursor string                     `json:"nextCursor,omitempty"`
}

type WorkflowRunCancelResponse struct {
	Run      WorkflowRunResponse       `json:"run"`
	Event    *WorkflowRunEventResponse `json:"event,omitempty"`
	Replayed bool                      `json:"replayed"`
}
