import { invoke as tauriInvoke } from '@tauri-apps/api/core'
import {
  desktopCommands,
  type DesktopContextResponse,
  type DesktopErrorEnvelope,
  type DesktopHistoryResponse,
  type DesktopImportSessionRequest,
  type DesktopImportSessionResponse,
  type DesktopMemoryActionRequest,
  type DesktopMemoryDraftRequest,
  type DesktopPromptOptimizeRequest,
  type DesktopPromptOptimizeResponse,
  type DesktopRecordLookupRequest,
  type DesktopRecordResponse,
  type DesktopRouteRequest,
  type DesktopSessionActionRequest,
  type DesktopSessionActionResponse,
  type DesktopSessionBrowserRequest,
  type DesktopSessionBrowserResponse,
  type DesktopSessionDetailRequest,
  type DesktopSessionDetailResponse,
  type DesktopStatusRequest,
  type DesktopStatusResponse,
  type DesktopWakeupRequest,
  type DesktopWakeupResponse,
  type DesktopWikiIndexRequest,
  type DesktopWikiIndexResponse,
  type DesktopWikiLintRequest,
  type DesktopWikiLintResponse,
  type DesktopWorkbenchRequest,
  type DesktopWorkbenchResponse,
  type DesktopWriteResponse,
} from '@/lib/types/desktop'

export class DesktopIpcError extends Error {
  readonly envelope: DesktopErrorEnvelope

  constructor(envelope: DesktopErrorEnvelope) {
    super(envelope.message)
    this.envelope = envelope
    this.name = 'DesktopIpcError'
  }
}

function isEnvelope(value: unknown): value is DesktopErrorEnvelope {
  return (
    typeof value === 'object' &&
    value !== null &&
    'kind' in value &&
    'message' in value &&
    'hint' in value &&
    'explain' in value
  )
}

async function call<T>(command: string, command_payload: unknown): Promise<T> {
  try {
    return await tauriInvoke<T>(command, { command: command_payload })
  } catch (raw) {
    if (isEnvelope(raw)) {
      throw new DesktopIpcError(raw)
    }
    throw new DesktopIpcError({
      kind: 'runtime',
      message: raw instanceof Error ? raw.message : String(raw),
      hint: '请查看 explain 中的原始错误，并结合输入与配置继续排查。',
      explain: raw instanceof Error ? raw.stack ?? raw.message : String(raw),
    })
  }
}

export const ipc = {
  runContext: (req: DesktopRouteRequest) =>
    call<DesktopContextResponse>(desktopCommands.runContext, req),
  buildWakeup: (req: DesktopWakeupRequest) =>
    call<DesktopWakeupResponse>(desktopCommands.buildWakeup, req),
  optimizePrompt: (req: DesktopPromptOptimizeRequest) =>
    call<DesktopPromptOptimizeResponse>(desktopCommands.optimizePrompt, req),
  loadWorkbench: (req: DesktopWorkbenchRequest) =>
    call<DesktopWorkbenchResponse>(desktopCommands.loadWorkbench, req),
  getRecord: (req: DesktopRecordLookupRequest) =>
    call<DesktopRecordResponse | null>(desktopCommands.getRecord, req),
  getHistory: (req: DesktopRecordLookupRequest) =>
    call<DesktopHistoryResponse>(desktopCommands.getHistory, req),
  browseSessions: (req: DesktopSessionBrowserRequest) =>
    call<DesktopSessionBrowserResponse>(desktopCommands.browseSessions, req),
  getSession: (req: DesktopSessionDetailRequest) =>
    call<DesktopSessionDetailResponse | null>(desktopCommands.getSession, req),
  collectStatus: (req: DesktopStatusRequest) =>
    call<DesktopStatusResponse>(desktopCommands.collectStatus, req),
  continueSession: (req: DesktopSessionActionRequest) =>
    call<DesktopSessionActionResponse>(desktopCommands.continueSession, req),
  deleteSession: (req: DesktopSessionActionRequest) =>
    call<DesktopSessionActionResponse>(desktopCommands.deleteSession, req),
  recordManual: (req: DesktopMemoryDraftRequest) =>
    call<DesktopWriteResponse>(desktopCommands.recordManual, req),
  proposeMemory: (req: DesktopMemoryDraftRequest) =>
    call<DesktopWriteResponse>(desktopCommands.proposeMemory, req),
  applyMemoryAction: (req: DesktopMemoryActionRequest) =>
    call<DesktopWriteResponse>(desktopCommands.applyMemoryAction, req),
  importSession: (req: DesktopImportSessionRequest) =>
    call<DesktopImportSessionResponse>(desktopCommands.importSession, req),
  wikiLint: (req: DesktopWikiLintRequest) =>
    call<DesktopWikiLintResponse>(desktopCommands.wikiLint, req),
  readWikiIndex: (req: DesktopWikiIndexRequest) =>
    call<DesktopWikiIndexResponse>(desktopCommands.readWikiIndex, req),
}

export const isTauriHost = () =>
  typeof window !== 'undefined' &&
  Boolean((window as unknown as { __TAURI_INTERNALS__?: unknown }).__TAURI_INTERNALS__ ??
    (window as unknown as { __TAURI__?: unknown }).__TAURI__)
