import type { BrowserWindow, IpcMain } from 'electron'
import type {
  CapabilityTool,
  CapabilityToolEntry,
  CustomAgentConfig,
  DestructiveConfirmationRequest,
  RuntimeContextOptions,
  ScopedArtifactRef,
  SessionArtifactRequest,
  ToolListOptions,
} from '@open-cowork/shared'
import type { OpencodeClient } from '@opencode-ai/sdk/v2'
import type { SessionRecord } from '../session-registry'
import type { NativeConfirmationOptions } from '../native-confirmation.ts'
import type { WorkspaceGateway } from '../workspace-gateway.ts'
import type { DesktopPairingService } from '../desktop-pairing/service.ts'

export type SessionClientContext = {
  client: OpencodeClient
  record: SessionRecord | null
}

export type SessionV2ClientContext = {
  client: OpencodeClient
  record: SessionRecord
  directory: string
}

export type IpcHandlerContext = {
  ipcMain: Pick<IpcMain, 'handle' | 'on'>
  workspaceGateway: WorkspaceGateway
  desktopPairingService: DesktopPairingService
  getMainWindow: () => BrowserWindow | null
  normalizeDirectory: (directory?: string | null) => string
  ensureSessionRecord: (sessionId: string) => SessionRecord | null
  resolvePrivateArtifactPath: (request: SessionArtifactRequest) => { root: string; source: string }
  grantProjectDirectory: (directory: string) => string
  resolveGrantedProjectDirectory: (directory?: string | null) => string | null
  resolveContextDirectory: (options?: RuntimeContextOptions) => string | null
  resolveScopedTarget: <T extends ScopedArtifactRef>(target: T) => T & { directory: string | null }
  buildCustomAgentPermission: (agent: CustomAgentConfig, options?: RuntimeContextOptions) => Promise<Record<string, unknown>>
  requestNativeConfirmation: (options: NativeConfirmationOptions) => Promise<boolean>
  logHandlerError: (handler: string, err: unknown) => void
  describeDestructiveRequest: (request: DestructiveConfirmationRequest) => string
  consumeDestructiveConfirmation: (request: DestructiveConfirmationRequest, token?: string | null) => boolean
  reconcileIdleSession: (sessionId: string) => void
  getSessionClient: (sessionId: string) => Promise<SessionClientContext>
  getSessionV2Client: (sessionId: string) => Promise<SessionV2ClientContext>
  listRuntimeTools: (options?: ToolListOptions) => Promise<unknown[]>
  withDiscoveredBuiltInTools: (
    tools: CapabilityTool[],
    runtimeTools: unknown[],
    options?: RuntimeContextOptions & { deep?: boolean; discoveryTimeoutMs?: number; signal?: AbortSignal },
  ) => Promise<CapabilityTool[]>
  listToolsFromMcpEntry: (entry: unknown, options?: { timeoutMs?: number; signal?: AbortSignal }) => Promise<CapabilityToolEntry[]>
  isLikelyMcpAuthError: (error: unknown) => boolean
  authenticateNewRemoteMcpIfNeeded: (name: string) => Promise<void>
  approvedSkillImportDirectories: Map<string, string>
  capabilityToolMethodCache: Map<string, { expiresAt: number; entries: CapabilityToolEntry[] }>
}
