// Global type extensions for Hermes WebUI
// Patches for loosely-typed legacy JavaScript code

interface WsEntry {
  name: string;
  path: string;
  type: 'file' | 'dir' | string;
  size?: number;
  modified?: number;
}

interface State {
  session: any;
  messages: any[];
  entries: any[];
  busy: boolean;
  pendingFiles: any[];
  toolCalls: any[];
  activeStreamId: any;
  currentDir: string;
  activeProfile: string;
  _expandedDirs?: Set<string>;
  _dirCache?: Record<string, WsEntry[]>;
  _profileDefaultWorkspace?: string;
  lastUsage?: Record<string, unknown>;
  activityTree?: ActivityTree | null;
  mcFilter?: MCFilter;
  mcSort?: 'runtime' | 'agent' | 'status';
  [key: string]: any;
}

declare const t: any;

interface HTMLInputElement {
  value: string;
  disabled: boolean;
  files: FileList | null;
  checked?: boolean;
}

interface HTMLTextAreaElement {
  value: string;
}

interface HTMLSelectElement {
  value: string;
  options: HTMLOptionsCollection;
  selectedIndex: number;
  readonly children: HTMLCollectionOf<HTMLOptGroupElement | HTMLOptionElement>;
  readonly childElementCount: number;
  item(index: number): HTMLOptGroupElement | HTMLOptionElement | null;
  namedItem(name: string): HTMLOptionElement | null;
}

interface HTMLOptionElement {
  value: string;
  text: string;
  disabled: boolean;
  defaultSelected: boolean;
  selected: boolean;
  index: number;
  form: HTMLFormElement | null;
}

interface HTMLOptGroupElement {
  disabled: boolean;
  label: string;
  readonly children: HTMLCollectionOf<HTMLOptionElement>;
}

interface HTMLElement {
  disabled?: boolean;
  value?: string;
  files?: FileList | null;
  checked?: boolean;
  placeholder?: string;
  innerHTML?: string;
  innerText?: string;
  textContent?: string;
  title?: string;
  style?: CSSStyleDeclaration & { [key: string]: string } & { cssText?: string };
  className?: string;
  id?: string;
  dataset?: DOMStringMap;
  offsetWidth?: number;
  offsetHeight?: number;
  offsetLeft?: number;
  offsetTop?: number;
  scrollIntoView?: (options?: any) => void;
  getBoundingClientRect?: () => DOMRect;
  contains?: (node: Node) => boolean;
  closest?: (selectors: string) => HTMLElement | null;
  classList?: DOMTokenList & { add(...classes: string[]): void; remove(...classes: string[]): void; toggle(c: string, force?: boolean): boolean; contains(c: string): boolean; };
  setAttribute(name: string, value: string): void;
  getAttribute(name: string): string | null;
  removeAttribute(name: string): void;
  addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
  removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
  dispatchEvent(event: Event): boolean;
  appendChild(node: Node | Element | HTMLElement | HTMLButtonElement | HTMLDivElement | HTMLSpanElement | HTMLInputElement | HTMLOptGroupElement): Node;
  removeChild(node: Node | Element | HTMLElement | HTMLButtonElement | HTMLDivElement | HTMLSpanElement | HTMLInputElement | HTMLOptGroupElement): Node;
  replaceWith(...nodes: (Node | string)[]): void;
  insertAdjacentHTML(position: 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend', html: string): void;
  insertAdjacentElement(position: 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend', element: HTMLElement): HTMLElement | null;
  click(): void;
  focus(): void;
  blur(): void;
  scrollTo(x: number, y: number): void;
  requestFullscreen?: () => Promise<void>;
  matches?(selector: string): boolean;
  replaceWith(...nodes: any[]): void;
  _t?: ReturnType<typeof setTimeout>;
  after(...nodes: (Node | string)[]): void;
}

interface Window {
  webkitSpeechRecognition: any;
  SpeechRecognition: any;
  _stopMic: () => void;
  _micActive: boolean;
  _micPendingSend: boolean;
  _sendKey: string;
  _showTokenUsage: boolean;
  _showCliSessions: boolean;
  _soundEnabled: boolean;
  _notificationsEnabled: boolean;
  _botName: string;
  _previewCurrentPath: string;
  _previewCurrentMode: string;
  _previewDirty: boolean;
  _initResizePanels: () => void;
  showSaveFilePicker?: (options?: any) => Promise<any>;
  showOpenFilePicker?: (options?: any) => Promise<any>;
  _activeProvider: string | null;
  t: any;
  _userEmoji: string;
  _userName: string;
  _updateData: any;
  _escHandler: any;
  _saveExpandedDirs: any;
  _mcPriorityFilter: any;
  cancelEditMode: () => void;
  cancelEdit: () => void;
  closeAgentDetail: () => void;
  switchToChatPanel: () => void;
  stopGatewaySSE: () => void;
  updateWorkspaceChip: () => void;
  _showAllProfiles: () => void;
  showPreview: (type: string) => void;
  cancelEditMode: () => void;
  _previewDirty: boolean;
}

declare var Prism: any;
declare var mermaid: any;
declare var katex: any;

declare function li(name: string, size?: number): string;
declare function openFile(path: string, line?: number): void;

interface Session {
  session_id: string;
  messages?: Message[];
  workspace?: string;
  input_tokens?: number;
  output_tokens?: number;
  estimated_cost?: number;
  last_usage?: Record<string, unknown>;
  tool_calls?: any[];
  active_stream_id?: string;
  pending_attachments?: unknown[];
  [key: string]: any;
}

interface Message {
  id?: string;
  role: string;
  content?: string | any[];
  tool_calls?: any[];
  name?: string;
  [key: string]: any;
}

declare const IMAGE_EXTS: Set<string>;
declare const MD_EXTS: Set<string>;
declare const DOWNLOAD_EXTS: Set<string>;

interface Document {
  exitFullscreen?: () => Promise<void>;
  fullscreenElement?: Element;
  pictureInPictureElement?: Element;
  documentMode?: any;
}

interface Element {
  scrollIntoViewIfNeeded?: (centerIfNeeded?: boolean) => void;
  onclick?: (ev: MouseEvent) => any;
  oninput?: (ev: InputEvent) => any;
  onkeydown?: (ev: KeyboardEvent) => any;
  onkeyup?: (ev: KeyboardEvent) => any;
  onchange?: (ev: Event) => any;
  style?: CSSStyleDeclaration & { [key: string]: string };
  closest?: (selectors: string) => HTMLElement | null;
  dataset?: DOMStringMap;
  classList?: DOMTokenList & { add(...classes: string[]): void; remove(...classes: string[]): void; toggle(c: string, force?: boolean): boolean; contains(c: string): boolean; };
  appendChild<T extends Node>(node: T): T;
  removeChild<T extends Node>(node: T): T;
  getAttribute(name: string): string | null;
  setAttribute(name: string, value: string): void;
  removeAttribute(name: string): void;
  appendChild(node: Node | Element | HTMLElement | HTMLButtonElement | HTMLDivElement | HTMLSpanElement | HTMLInputElement | HTMLOptGroupElement): Node;
  removeChild(node: Node | Element | HTMLElement | HTMLButtonElement | HTMLDivElement | HTMLSpanElement | HTMLInputElement | HTMLOptGroupElement): Node;
  addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: Element, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
  removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: Element, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
  contains(node: Node): boolean;
  replaceWith(...nodes: any[]): void;
  textContent?: string;
  innerHTML?: string;
}

declare function escape(html: string): string;
declare function highlightCode(container?: any): void;
declare function showToast(msg: string, ms?: number): void;
declare function setStatus(msg: string): void;
declare function setComposerStatus(msg: string): void;
declare function loadWorkspaceList(): Promise<any>;
declare function syncOnboardingProvider(value: string): void;
declare function syncOnboardingWorkspaceSelect(value: string): void;
declare function fileIcon(name: string, type: string): string;
declare function loadOnboardingWizard(): Promise<boolean>;
declare function nextOnboardingStep(): Promise<void>;
declare function prevOnboardingStep(): void;
declare function skipOnboarding(): Promise<void>;
declare function renderSessionList(): Promise<void>;
declare function newSession(flash?: boolean, agentOverride?: string): Promise<void>;
declare function updateQueueBadge(sid?: string): void;
declare function stopApprovalPolling(): void;
declare function hideApprovalCard(): void;
declare function updateSendBtn(): void;
declare function syncTopbar(): void;
declare function renderMessages(): void;
declare function loadDir(path: string): Promise<void>;
declare function loadSession(sid: string): Promise<void>;
declare function executeCommand(text: string): boolean;
declare function isCompressionUiRunning(): boolean;
declare const _allSessions: any[];
declare function renderSessionListFromCache(): void;
declare const _assistantTurnBlocks: any;
declare function placeLiveToolCardsHost(): void;
declare function finalizeThinkingCard(): void;

declare const _: any;
declare const jQuery: any;
declare const LOCALES: any;

interface ConfigData {
  default_model?: string;
  send_key?: string;
  theme?: string;
  language?: string;
  show_token_usage?: boolean;
  show_cli_sessions?: boolean;
  sync_to_insights?: boolean;
  check_for_updates?: boolean;
  sound_enabled?: boolean;
  notifications_enabled?: boolean;
  bubble_layout?: string;
  bot_name?: string;
  user_emoji?: string;
  user_name?: string;
  [key: string]: any;
}

declare function stopGateway(): void;
declare function stopGatewaySSE(): void;
declare function cancelEdit(): void;
declare function watchInflightSession(sid: string, activeStreamId: string): void;
declare function showPreview(type: string): void;
declare function cancelEditMode(): void;
declare function clearPreview(): void;
declare function closeAgentDetail(): void;
declare function switchToChatPanel(): void;
declare function updateWorkspaceChip(): void;
declare let _showAllProfiles: boolean;
declare let _escHandler: any;
declare let _previewDirty: boolean;
declare function _saveExpandedDirs(): void;
declare function highlightCode(container?: any): void;
declare function addCopyButtons(): void;
declare function renderMermaidBlocks(): void;
declare function renderKatexBlocks(): void;
declare function openFile(path: string, line?: number): void;
declare const fileExt: any;
interface DialogOpts {
  title?: string;
  message?: string;
  inputType?: string;
  value?: string;
  placeholder?: string;
  cancelLabel?: string;
  confirmLabel?: string;
  danger?: boolean;
  focusCancel?: boolean;
}
declare function showConfirmDialog(opts?: DialogOpts): Promise<boolean>;
declare function showPromptDialog(opts?: DialogOpts): Promise<string | null>;

// Global state variables used across modules
declare let assistantText: string;
declare let _reasoningText: string;
declare let liveReasoningText: string;
declare function persistInflightState(sid: string, state: any): void;
declare function clearInflightState(sid: string): void;
declare function markInflight(sid: string, streamId: string): void;
declare function clearInflight(): void;
declare function saveInflightState(sid: string, state: any): void;
declare function loadInflightState(sid: string, streamId: string): any;
declare function startApprovalPolling(sid: string): void;
declare function stopApprovalPolling(): void;
declare function startClarifyPolling(sid: string): void;
declare function stopClarifyPolling(): void;
declare function cancelStream(): void;
declare function appendLiveToolCard(tc: any): void;
declare function buildToolCard(tc: any, live?: boolean): string;
declare function finalizeThinkingCard(): void;
declare function syncInflightAssistantMessage(): void;
declare function setBusy(busy: boolean): void;
declare function attachLiveStream(sid: string, streamId: string, uploaded?: any[], opts?: any): void;
declare function isCompressionUiRunning(): boolean;

// ─── Agent Activity Tree (Mission Control) ──────────────────────────
interface ActivityToolCall {
  id: string;
  name: string;
  status: 'pending' | 'running' | 'done' | 'error';
  args: Record<string, any>;
  result?: string;
  duration?: number;
  startedAt: number | null;
  endedAt: number | null;
}

interface ActivityNode {
  id: string;
  parentId: string | null;
  agentId: string;
  agentEmoji: string;
  agentName: string;
  tier: 1 | 2 | 3;
  status: 'pending' | 'running' | 'thinking' | 'done' | 'error' | 'cancelled';
  task: string;
  toolCalls: ActivityToolCall[];
  startedAt: number | null;
  endedAt: number | null;
  duration: number | null;
  children: string[];
  collapsed: boolean;
  metadata: Record<string, any>;
}

interface MCStats {
  totalAgents: number;
  runningAgents: number;
  pendingAgents: number;
  doneAgents: number;
  errorAgents: number;
  totalTools: number;
  doneTools: number;
  runningTools: number;
  avgResponseTime: number;
  totalElapsed: number;
}

interface ActivityTree {
  version: 1;
  rootId: string;
  nodes: Record<string, ActivityNode>;
  stats: MCStats;
}

interface MCFilter {
  agent?: string;
  status?: string;
  search?: string;
}

declare function initActivityTree(): ActivityTree;
declare function createMockActivityTree(): ActivityTree;
declare function formatElapsed(ms: number): string;
