import type {
  SessionQueueErrorCode,
  SessionQueueItem,
  SessionQueueStatus,
} from '#cli/core/session-meta'
import type { DimSdkStore } from '#cli/core/store'
import type { ProviderAdapter } from '#cli/compat/providers'
import type { Style, TerminalRouter } from '@simon_he/vue-tui'
import type { ComputedRef, InjectionKey, Ref } from 'vue'
import type {
  DimSdkSessionListItem,
  DimSdkSessionTrace,
  DimSdkSessionsApi,
} from '../../keys'
import type {
  AskUserInlineState,
  Line,
  LineAction,
} from '../../ui/chat/layout-model'
import type { CommandPaletteOption } from '../../ui/components/CommandPalette'
import type { MessageActionsMode } from '../../ui/components/MessageActionsDialog'
import type { UiThemeContext } from '../../ui/theme'

type AskUserPanelAction =
  | { type: 'option'; index: number }
  | { type: 'nav'; direction: 'prev' | 'next' }
  | { type: 'optionFocus'; direction: 'up' | 'down' }
  | { type: 'focus'; target: 'options' | 'input' }
  | { type: 'toggleFocused' }
  | { type: 'activate' }
  | { type: 'submit' }
  | { type: 'cancel' }

export type ChatPageContext = Readonly<{
  nodeLike: boolean
  ui: UiThemeContext

  router: TerminalRouter
  store: DimSdkStore
  sessionsApi?: DimSdkSessionsApi

  invalidate: () => void

  anyDialogOpen: ComputedRef<boolean>

  cols: ComputedRef<number>
  rows: ComputedRef<number>
  contentW: ComputedRef<number>

  mainY: number
  mainW: ComputedRef<number>
  mainH: ComputedRef<number>

  scrollTop: Ref<number>
  maxScroll?: ComputedRef<number>
  stickToBottom?: Ref<boolean>
  visibleLines: ComputedRef<readonly Line[]>
  visibleStartRow: ComputedRef<number>
  messageRoleById: ComputedRef<Map<string, 'user' | 'assistant' | 'tool'>>

  messageSelectStart: Ref<{ row: number; col: number } | null>
  messageSelectEnd: Ref<{ row: number; col: number } | null>
  focusMode: Ref<'input' | 'messages'>
  hoveredUserMessageId: Ref<string | null>
  hoveredLink: Ref<boolean>
  hoveredLinkRange: Ref<{
    row: number
    startCol: number
    endCol: number
  } | null>

  onWheel: (e: any) => void
  onSelectionKeydown: (e: any) => void
  onMessageClick: (e: any) => void
  onMessagePointerDown: (e: any) => void
  onMessagePointerMove: (e: any) => void
  onMessagePointerUp: (e: any) => void
  onMessageContextMenu: (e: any) => void
  onLineClick: (action?: LineAction) => void

  focusBrowserTextarea: () => void
  showCopyToast: (text: string) => void
  copyToastVisible: Ref<boolean>
  copyToastText: Ref<string>

  sessionHeaderTitle: ComputedRef<string>
  sessionHeaderSummary: ComputedRef<string>
  headerStatsDisplay: ComputedRef<string>

  panelW: ComputedRef<number>
  panelX: ComputedRef<number>
  panelTopY: ComputedRef<number>
  panelH: ComputedRef<number>

  inputX: ComputedRef<number>
  inputInnerW: ComputedRef<number>
  inputLines: ComputedRef<number>
  modelRowGap: ComputedRef<number>

  input: Ref<string>
  inputPlaceholder: ComputedRef<string>
  focusFiles: Ref<string[]>
  multilineTexts: Ref<string[]>
  setMultilineTexts: (
    nextTexts: readonly string[],
    opts?: Readonly<{ deleteRemoved?: boolean }>,
  ) => Promise<void>
  handleMultilineClick: (index: number) => Promise<void>
  pickerWorkspace: ComputedRef<string>
  promptSuggestions: ComputedRef<
    readonly {
      value: string
      insert?: string
      detail?: string
      keywords?: readonly string[]
      onSelect?: (
        info: Readonly<{ value: string; query: string }>,
      ) => void | boolean
    }[]
  >
  skillSuggestions: ComputedRef<readonly { value: string; detail: string }[]>

  showCommands: Ref<boolean>
  showHelp: Ref<boolean>
  showTheme: Ref<boolean>
  themeMode: Ref<string>
  applyTheme: () => void
  closeTheme: () => void
  showSessions: Ref<boolean>
  showTimeline: Ref<boolean>
  showSessionTrace: Ref<boolean>
  showPinned: Ref<boolean>
  showMessageActions: Ref<boolean>
  messageActionsMode: Ref<MessageActionsMode>
  showRedoConfirm: Ref<boolean>
  showConfig: Ref<boolean>
  showConnect: Ref<boolean>
  showModels: Ref<boolean>
  showConnectDialog: Ref<boolean>
  showCustomManage: Ref<boolean>
  showCustomDeleteConfirm: Ref<boolean>
  showNextApiOAuth: Ref<boolean>
  showToolApprovals: Ref<boolean>
  showApproval: Ref<boolean>
  showPathPicker: Ref<boolean>
  showExitConfirm: Ref<boolean>
  showRenameSession: Ref<boolean>
  showSkills: Ref<boolean>
  showToolSettings: Ref<boolean>
  showMcpSettings: Ref<boolean>
  showPlugins: Ref<boolean>
  showPluginConfig: Ref<boolean>

  pathPickerMode: Ref<'directory' | 'file'>
  pathPickerQuery: Ref<string>
  pathPickerError: Ref<string | null>

  send: (v: string) => void
  onInputKeydown: (e: any) => void
  setContextCwd: (absPath: string) => void

  queueItems: ComputedRef<readonly SessionQueueItem[]>
  queueStatus: ComputedRef<SessionQueueStatus>
  pausedQueueDecisionVisible: Ref<boolean>
  pausedQueueDecisionSummary: ComputedRef<string>
  queueConfirmVisible: Ref<boolean>
  queueConfirmReason: Ref<SessionQueueErrorCode | null>
  summarizeQueueText: (text: string, maxCells?: number) => string
  deleteQueueItem: (id: string) => void
  upgradeQueueItemToSteer: (id: string) => Promise<void>
  continuePausedQueueDecision: () => void
  appendPausedQueueDecision: () => void
  replacePausedQueueDecision: () => Promise<void>
  confirmQueueResume: () => void
  pauseQueueResume: () => void

  ctxPctChip: ComputedRef<string>
  ctxPctStyle: ComputedRef<Style>
  modelInfo: ComputedRef<{ build: string; model: string; providerName: string }>
  modeLabel: ComputedRef<string>
  assistantStatusDisplay: ComputedRef<string>
  assistantStatusStyle: ComputedRef<Style>
  thinkingStatusDisplay: ComputedRef<string>
  thinkingStatusStyle: ComputedRef<Style>

  footerH: number
  footerRight: ComputedRef<string>
  footerRightFull: ComputedRef<string>
  footerRightCompact: ComputedRef<string>
  footerRightMicro: ComputedRef<string>
  footerRightMini: ComputedRef<string>
  isLoading: ComputedRef<boolean>
  loadingSpinnerCols: ComputedRef<readonly [Style, Style]>
  loadingSpinnerGlyph: ComputedRef<string>
  loadingSpinnerGlyphStyle: ComputedRef<Style>

  commandOptions: ComputedRef<readonly { label: string; detail?: string }[]>
  commandIndex: Ref<number>
  onCommandSelect: (v: string | null) => void
  closeCommandPalette: () => void

  helpOptions: ComputedRef<
    readonly { label: string; detail?: string; keywords?: readonly string[] }[]
  >
  helpIndex: Ref<number>
  openHelp: () => void
  closeHelp: () => void

  timelineOptions: ComputedRef<
    readonly { label: string; detail?: string; keywords?: readonly string[] }[]
  >
  timelineIndex: Ref<number>
  onTimelineSelect: (v: string | null) => void
  closeTimeline: () => void

  sessionTrace: Ref<DimSdkSessionTrace | null>
  sessionTraceLoading: Ref<boolean>
  sessionTraceError: Ref<string>
  sessionTraceIndex: Ref<number>
  openSessionTrace: () => Promise<void>
  closeSessionTrace: () => void
  refreshSessionTrace: () => Promise<void>

  pinnedOptions: ComputedRef<
    readonly { label: string; detail?: string; keywords?: readonly string[] }[]
  >
  pinnedIndex: Ref<number>
  onPinnedSelect: (v: string | null) => void
  closePinned: () => void

  customManageTitle: ComputedRef<string>
  customManageOptions: ComputedRef<readonly CommandPaletteOption[]>
  customManageIndex: Ref<number>
  onSelectCustomManage: (v: string | null) => void
  closeCustomManage: () => void

  customDeleteConfirmTitle: ComputedRef<string>
  customDeleteConfirmOptions: ComputedRef<readonly CommandPaletteOption[]>
  customDeleteConfirmIndex: Ref<number>
  onSelectCustomDeleteConfirm: (v: string | null) => void
  closeCustomDeleteConfirm: () => void

  providerOptions: ComputedRef<readonly { label: string; detail?: string }[]>
  providerIndex: Ref<number>
  modelOptions: ComputedRef<readonly { label: string; detail?: string }[]>
  modelIndex: Ref<number>
  onSelectProvider: (v: string | null) => void
  onSelectModel: (v: string | null) => void
  closeConnect: () => void
  closeModels: () => void

  refreshSessions: (opts?: {
    preferIndex?: number
    preferId?: string
  }) => Promise<void>
  sessionsLoading: Ref<boolean>
  sessionsDeleteArmed: Ref<boolean>
  sessionsCwdOnly: Ref<boolean>
  sessionsAllCount: Ref<number>
  sessionsList: Ref<DimSdkSessionListItem[]>
  sessionsIndex: Ref<number>
  showSwitchConfirm: Ref<boolean>
  switchConfirmTitle: Ref<string>
  switchConfirmTargetLabel: Ref<string>
  switchConfirmReason: Ref<string>
  openSelectedSession: (opts?: {
    after?: () => void | Promise<void>
  }) => Promise<void>
  createNewSession: (opts?: {
    after?: () => void | Promise<void>
  }) => Promise<void>
  confirmSwitch: () => Promise<void>
  cancelSwitch: () => void

  messageActionsIndex: Ref<number>
  messageActionsTargetId: Ref<string | null>
  handleRevertMessage: () => void
  handleRevertTurnMessageAndFiles: () => void
  handleRevertMessageKeepFiles: () => void
  handleRevertFilesOnly: () => void
  handleCopyMessage: () => void
  handleForkSession: () => void
  handlePinMessage: () => void
  isMessagePinned: (id: string) => boolean

  confirmRestore: () => void
  cancelRestore: () => void

  pickerW: ComputedRef<number>
  pickerH: ComputedRef<number>
  pathPickerTitle: ComputedRef<string>
  pathPickerPlaceholder: ComputedRef<string>

  configW: ComputedRef<number>
  configH: ComputedRef<number>
  smW: ComputedRef<number>
  smH: ComputedRef<number>
  mdW: ComputedRef<number>
  mdH: ComputedRef<number>
  contextWindow: Ref<string>
  contextWindowLocked: Ref<boolean>
  maxTokens: Ref<string>
  temperature: Ref<string>
  interleavedThinking: Ref<boolean>
  interleavedThinkingLocked: Ref<boolean>
  shortcutCommands: Ref<string>
  shortcutTimeline: Ref<string>
  shortcutNewSession: Ref<string>
  applyConfig: () => void
  closeConfig: () => void

  languageW: ComputedRef<number>
  languageH: ComputedRef<number>
  showLanguage: Ref<boolean>
  locale: Ref<string>
  applyLanguage: () => void
  closeLanguage: () => void

  connectProviderName: ComputedRef<string>
  connectProviderAdapter: ComputedRef<ProviderAdapter>
  connectBaseUrl: Ref<string>
  updateConnectBaseUrlDraft: (value: string) => void
  connectApiKeyDraft: Ref<string>
  connectApiKeyMasked: ComputedRef<string>
  connectCanClearKey: ComputedRef<boolean>
  connectApplying: Ref<boolean>
  connectFocusKey: Ref<boolean>
  connectBaseUrlMode: Ref<'editable' | 'readonly' | 'hidden'>
  connectBaseUrlAfterApiKey: Ref<boolean>
  applyConnect: () => void
  clearConnectKey: () => void
  cancelConnectDialog: () => void

  showCustomType: Ref<boolean>
  customTypeOptions: ComputedRef<readonly { label: string; detail?: string }[]>
  customTypeIndex: Ref<number>
  onSelectCustomType: (v: string | null) => void
  closeCustomType: () => void

  showCustomConnectDialog: Ref<boolean>
  customConnectAdapter: ComputedRef<ProviderAdapter>
  customConnectBaseUrl: Ref<string>
  updateCustomConnectBaseUrlDraft: (value: string) => void
  customConnectApiKeyDraft: Ref<string>
  customConnectApiKeyMasked: ComputedRef<string>
  customConnectFocusKey: Ref<boolean>
  applyCustomConnect: () => void
  cancelCustomConnectDialog: () => void

  showCustomModelsDialog: Ref<boolean>
  customModelsDraft: Ref<string>
  customModelsFetching: Ref<boolean>
  openCustomModelsFetch: () => void
  applyCustomModels: () => void
  cancelCustomModelsDialog: () => void

  showCustomModelsFetchDialog: Ref<boolean>
  customModelsFetchOptions: Ref<readonly { label: string; detail?: string }[]>
  customModelsFetchSelected: Ref<number[]>
  applyCustomModelsFetch: (indices: number[]) => void
  cancelCustomModelsFetchDialog: () => void

  showCustomNameDialog: Ref<boolean>
  customNameDraft: Ref<string>
  applyCustomName: () => void
  cancelCustomNameDialog: () => void
  nextApiOAuthStatus: Ref<'loading' | 'authenticated' | 'unauthenticated'>
  nextApiOAuthEmail: Ref<string>
  nextApiOAuthUrl: Ref<string>
  nextApiOAuthError: Ref<string>
  selectedNextApiModel: Ref<string>
  nextApiModels: Ref<Array<{ id: string; name: string; description: string }>>
  nextApiModelIndex: Ref<number>
  closeNextApiOAuth: () => void
  loginWithNextApiOAuth: () => void
  logoutNextApiOAuth: () => void
  selectNextApiModel: (modelId: string) => void
  viewNextApiPlans: () => void

  toolApprovalsW: ComputedRef<number>
  toolApprovalsH: ComputedRef<number>
  applyToolApprovals: (mode: 'auto' | 'normal' | 'strict') => void

  toolSettingsW: ComputedRef<number>
  toolSettingsH: ComputedRef<number>
  toolApiKeyDraft: Ref<string>
  toolApiKeyMasked: ComputedRef<string>
  applyToolSettings: () => void
  closeToolSettings: () => void

  mcpSettingsW: ComputedRef<number>
  mcpSettingsH: ComputedRef<number>

  pluginsTitle: ComputedRef<string>
  pluginsOptions: ComputedRef<
    readonly { label: string; detail?: string; keywords?: readonly string[] }[]
  >
  pluginsIndex: Ref<number>
  onPluginSelect: (label: string | null) => void
  openPlugins: () => void
  closePlugins: () => void
  pluginApiKeyDraft: Ref<string>
  pluginApiKeyMasked: ComputedRef<string>
  openSerperConfig: () => void
  closeSerperConfig: () => void
  applySerperConfig: () => void
  mcpJsonFilePath: Ref<string>
  mcpServerCount: Ref<number>
  mcpTestStatus: Ref<{
    state: 'idle' | 'testing' | 'success' | 'error'
    message?: string
    results?: ReadonlyArray<{
      name: string
      toolCount?: number
      error?: string
      disabled?: boolean
    }>
  }>
  openMcpSettings: () => void
  closeMcpSettings: () => void
  openMcpFile: () => void
  reloadMcpConfig: () => void
  testMcpConnection: () => void

  activeApproval: ComputedRef<any>
  approvalActionIndex: Ref<number>
  handleToolApprovalAction: (
    action: 'approve' | 'alwaysApprove' | 'deny',
    requestId?: string,
  ) => void
  approvalW: ComputedRef<number>
  approvalH: ComputedRef<number>

  activeAskUser: ComputedRef<any>
  askUserState: Ref<AskUserInlineState | null>
  handleAskUserAction: (action: AskUserPanelAction) => boolean
  showAskUser: Ref<boolean>
  askUserW: ComputedRef<number>
  askUserH: ComputedRef<number>

  skillsOptions: ComputedRef<
    readonly { label: string; detail?: string; keywords?: readonly string[] }[]
  >
  skillsIndex: Ref<number>
  openSkills: () => void
  closeSkills: () => void
  onSkillSelect: (label: string | null) => void

  renameSessionW: ComputedRef<number>
  renameSessionH: ComputedRef<number>
  renameSessionInitialValue: ComputedRef<string>
  openRenameSession: () => void
  applyRenameSession: (title: string) => void
  cancelRenameSession: () => void

  exitSessionToHome: () => Promise<void>
}>

export const ChatPageContextKey: InjectionKey<ChatPageContext> = Symbol(
  'DimSdkChatPageContext',
)
