/**
 * Type and interface definitions for the Huskies API client.
 * All shared domain types — WebSocket messages, pipeline state,
 * provider configuration, and response shapes — live here.
 */

/** A message sent from the browser to the Huskies server over WebSocket. */
export type WsRequest =
	| {
			type: "chat";
			messages: Message[];
			config: ProviderConfig;
	  }
	| {
			type: "cancel";
	  }
	| {
			type: "permission_response";
			request_id: string;
			approved: boolean;
			always_allow: boolean;
	  }
	| { type: "ping" }
	| {
			type: "side_question";
			question: string;
			context_messages: Message[];
			config: ProviderConfig;
	  };

/** Metadata for a single step in the setup wizard flow. */
export interface WizardStepInfo {
	step: string;
	label: string;
	status: string;
	content?: string;
}

/** Full state snapshot of the setup wizard, including all steps and completion flag. */
export interface WizardStateData {
	steps: WizardStepInfo[];
	current_step_index: number;
	completed: boolean;
}

/** Describes the agent currently assigned to a pipeline work item. */
export interface AgentAssignment {
	agent_name: string;
	model: string | null;
	status: string;
}

/** Display column for a work item — derived server-side from `Stage::pipeline()` (story 1085). */
export type Pipeline =
	| "backlog"
	| "coding"
	| "qa"
	| "merge"
	| "done"
	| "closed"
	| "archived";

/** Badge/indicator for a work item — derived server-side from `Stage::status()` (story 1085). */
export type Status =
	| "active"
	| "frozen"
	| "review-hold"
	| "blocked"
	| "merge-failure"
	| "merge-failure-final"
	| "abandoned"
	| "superseded"
	| "rejected"
	| "done";

/** A single item in any pipeline stage (backlog, current, QA, merge, or done). */
export interface PipelineStageItem {
	story_id: string;
	name: string;
	error: string | null;
	merge_failure: string | null;
	agent: AgentAssignment | null;
	/** Display column (story 1085); falls back to the bucket name on legacy servers. */
	pipeline?: Pipeline;
	/** Display badge (story 1085); falls back to derived `blocked`/`frozen` on legacy servers. */
	status?: Status;
	review_hold: boolean | null;
	qa: string | null;
	depends_on: number[] | null;
	/** True when the item is in Stage::Blocked — awaiting human unblock. */
	blocked?: boolean | null;
	/** True when the item is in Stage::Frozen — paused at its current stage. */
	frozen?: boolean | null;
}

/** Snapshot of all pipeline stages returned via WebSocket or REST. */
export interface PipelineState {
	backlog: PipelineStageItem[];
	current: PipelineStageItem[];
	qa: PipelineStageItem[];
	merge: PipelineStageItem[];
	done: PipelineStageItem[];
	/** Story IDs that currently have a deterministic merge in progress. */
	deterministic_merges_in_flight: string[];
}

/** A message received from the Huskies server over WebSocket. */
export type WsResponse =
	| { type: "token"; content: string }
	| { type: "update"; messages: Message[] }
	| { type: "session_id"; session_id: string }
	| { type: "error"; message: string }
	| {
			type: "pipeline_state";
			backlog: PipelineStageItem[];
			current: PipelineStageItem[];
			qa: PipelineStageItem[];
			merge: PipelineStageItem[];
			done: PipelineStageItem[];
			deterministic_merges_in_flight: string[];
	  }
	| {
			type: "permission_request";
			request_id: string;
			tool_name: string;
			tool_input: Record<string, unknown>;
	  }
	| { type: "tool_activity"; tool_name: string }
	| {
			type: "reconciliation_progress";
			story_id: string;
			status: string;
			message: string;
	  }
	/** `.story_kit/project.toml` was modified; re-fetch the agent roster. */
	| { type: "agent_config_changed" }
	/** An agent started, stopped, or changed state; re-fetch agent list. */
	| { type: "agent_state_changed" }
	/** Heartbeat response confirming the connection is alive. */
	| { type: "pong" }
	/** Sent on connect when the project still needs onboarding (specs are placeholders). */
	| { type: "onboarding_status"; needs_onboarding: boolean }
	/** Sent on connect when a setup wizard is active. */
	| {
			type: "wizard_state";
			steps: WizardStepInfo[];
			current_step_index: number;
			completed: boolean;
	  }
	/** Streaming thinking token from an extended-thinking block, separate from regular text. */
	| { type: "thinking_token"; content: string }
	/** Streaming token from a /btw side question response. */
	| { type: "side_question_token"; content: string }
	/** Final signal that the /btw side question has been fully answered. */
	| { type: "side_question_done"; response: string }
	/** A single server log entry (bulk on connect, then live). */
	| { type: "log_entry"; timestamp: string; level: string; message: string }
	/** A structured pipeline status event from the status broadcaster. */
	| { type: "status_update"; event: StatusEvent };

/**
 * A structured pipeline status event emitted by the status broadcaster.
 *
 * The discriminant `type` field enables per-event-type rendering without
 * parsing strings. All fields from the original event are preserved so
 * future UI stories can add dedicated icons, banners, or filters.
 */
export type StatusEvent =
	| {
			type: "stage_transition";
			story_id: string;
			story_name: string;
			from_stage: string;
			to_stage: string;
	  }
	| {
			type: "merge_failure";
			story_id: string;
			story_name: string;
			reason: string;
	  }
	| {
			type: "story_blocked";
			story_id: string;
			story_name: string;
			reason: string;
	  }
	| {
			type: "rate_limit_warning";
			story_id: string;
			story_name: string;
			agent_name: string;
	  }
	| {
			type: "rate_limit_hard_block";
			story_id: string;
			story_name: string;
			agent_name: string;
			reset_at: string;
	  };

/** LLM provider configuration used when initiating a chat request. */
export interface ProviderConfig {
	provider: string;
	model: string;
	base_url?: string;
	enable_tools?: boolean;
	session_id?: string;
}

/** Valid role values for a chat message. */
export type Role = "system" | "user" | "assistant" | "tool";

/** An LLM tool call embedded in an assistant message. */
export interface ToolCall {
	id?: string;
	type: string;
	function: {
		name: string;
		arguments: string;
	};
}

/** A single chat message exchanged with the LLM. */
export interface Message {
	role: Role;
	content: string;
	tool_calls?: ToolCall[];
	tool_call_id?: string;
}

/** Anthropic model metadata returned by the models endpoint. */
export interface AnthropicModelInfo {
	id: string;
	context_window: number;
}

/** Content and metadata for a pipeline work item fetched from the server. */
export interface WorkItemContent {
	content: string;
	stage: string;
	name: string;
	agent: string | null;
	/** Origin JSON string (story 1088), or null for pre-origin items. */
	origin: string | null;
}

/** Result for a single test case from the server's test runner. */
export interface TestCaseResult {
	name: string;
	status: "pass" | "fail";
	details: string | null;
}

/** Combined unit and integration test results for a work item. */
export interface TestResultsResponse {
	unit: TestCaseResult[];
	integration: TestCaseResult[];
}

/** A file-system entry (file or directory) returned by listing endpoints. */
export interface FileEntry {
	name: string;
	kind: "file" | "dir";
}

/** A single file-search match with path and match count. */
export interface SearchResult {
	path: string;
	matches: number;
}

/** Per-agent token usage and cost breakdown within a story. */
export interface AgentCostEntry {
	agent_name: string;
	model: string | null;
	input_tokens: number;
	output_tokens: number;
	cache_creation_input_tokens: number;
	cache_read_input_tokens: number;
	total_cost_usd: number;
}

/** Total token cost for a work item, broken down by agent. */
export interface TokenCostResponse {
	total_cost_usd: number;
	agents: AgentCostEntry[];
}

/** A single token-usage record from the server's usage log. */
export interface TokenUsageRecord {
	story_id: string;
	agent_name: string;
	model: string | null;
	timestamp: string;
	input_tokens: number;
	output_tokens: number;
	cache_creation_input_tokens: number;
	cache_read_input_tokens: number;
	total_cost_usd: number;
}

/** All token-usage records returned by the usage endpoint. */
export interface AllTokenUsageResponse {
	records: TokenUsageRecord[];
}

/** Output captured from a shell command executed on the server. */
export interface CommandOutput {
	stdout: string;
	stderr: string;
	exit_code: number;
}

/** OAuth authentication status returned by the server. */
export interface OAuthStatus {
	authenticated: boolean;
	expired: boolean;
	expires_at: number;
	has_refresh_token: boolean;
}
