import { contextBridge, ipcRenderer } from 'electron'
import type { FileNode, AIPayload, RevisionMeta, Attachment, SearchFileResult, GlobalConfig } from '../renderer/types/editor'

interface SearchOptions {
  caseSensitive: boolean
  wholeWord: boolean
  isRegex: boolean
}

contextBridge.exposeInMainWorld('api', {
  listFiles: (): Promise<FileNode[]> => ipcRenderer.invoke('fs:listFiles'),

  readFile: (filePath: string): Promise<string> =>
    ipcRenderer.invoke('fs:readFile', filePath),

  writeFile: (filePath: string, content: string): Promise<void> =>
    ipcRenderer.invoke('fs:writeFile', filePath, content),

  streamAIMessage: (
    payload: AIPayload,
    onChunk: (chunk: string) => void
  ): Promise<void> => {
    return new Promise((resolve, reject) => {
      const chunkHandler = (_: Electron.IpcRendererEvent, chunk: string): void => {
        onChunk(chunk)
      }
      const doneHandler = (): void => {
        ipcRenderer.removeListener('ai:chunk', chunkHandler)
        ipcRenderer.removeListener('ai:done', doneHandler)
        ipcRenderer.removeListener('ai:error', errorHandler)
        resolve()
      }
      const errorHandler = (_: Electron.IpcRendererEvent, message: string): void => {
        ipcRenderer.removeListener('ai:chunk', chunkHandler)
        ipcRenderer.removeListener('ai:done', doneHandler)
        ipcRenderer.removeListener('ai:error', errorHandler)
        reject(new Error(message))
      }

      ipcRenderer.on('ai:chunk', chunkHandler)
      ipcRenderer.on('ai:done', doneHandler)
      ipcRenderer.on('ai:error', errorHandler)

      ipcRenderer.invoke('ai:streamMessage', payload).catch(reject)
    })
  },

  pickAttachments: (): Promise<Attachment[]> =>
    ipcRenderer.invoke('fs:pickAttachments'),

  removeAIListener: (): void => {
    ipcRenderer.removeAllListeners('ai:chunk')
    ipcRenderer.removeAllListeners('ai:done')
    ipcRenderer.removeAllListeners('ai:error')
  },

  getProjectWordCount: (): Promise<number> => ipcRenderer.invoke('fs:projectWordCount'),

  saveOrder: (order: Record<string, string[]>): Promise<void> =>
    ipcRenderer.invoke('fs:saveOrder', order),

  readSession: (): Promise<Record<string, unknown>> =>
    ipcRenderer.invoke('session:read'),

  writeSession: (data: Record<string, unknown>): Promise<void> =>
    ipcRenderer.invoke('session:write', data),

  saveRevision: (filePath: string, content: string): Promise<void> =>
    ipcRenderer.invoke('revisions:save', filePath, content),

  listRevisions: (filePath: string): Promise<RevisionMeta[]> =>
    ipcRenderer.invoke('revisions:list', filePath),

  loadRevision: (filePath: string, revisionId: string): Promise<string> =>
    ipcRenderer.invoke('revisions:load', filePath, revisionId),

  deleteRevision: (filePath: string, revisionId: string): Promise<void> =>
    ipcRenderer.invoke('revisions:delete', filePath, revisionId),

  renameNode: (oldPath: string, newName: string): Promise<string> =>
    ipcRenderer.invoke('fs:rename', oldPath, newName),

  deleteNode: (targetPath: string): Promise<void> =>
    ipcRenderer.invoke('fs:delete', targetPath),

  createFile: (parentPath: string, name: string): Promise<string> =>
    ipcRenderer.invoke('fs:createFile', parentPath, name),

  createDir: (parentPath: string, name: string): Promise<string> =>
    ipcRenderer.invoke('fs:createDir', parentPath, name),

  moveFile: (sourcePath: string, targetDirPath: string): Promise<string> =>
    ipcRenderer.invoke('fs:move', sourcePath, targetDirPath),

  openStoryBible: (): Promise<{ path: string; content: string }> =>
    ipcRenderer.invoke('fs:openStoryBible'),

  writeStoryBible: (content: string): Promise<string> =>
    ipcRenderer.invoke('fs:writeStoryBible', content),

  onMenuAction: (handler: (action: string) => void): (() => void) => {
    const listener = (_: Electron.IpcRendererEvent, action: string): void => handler(action)
    ipcRenderer.on('menu:action', listener)
    return () => ipcRenderer.removeListener('menu:action', listener)
  },

  searchFiles: (query: string, options: SearchOptions): Promise<SearchFileResult[]> =>
    ipcRenderer.invoke('fs:search', query, options),

  replaceInFiles: (query: string, replacement: string, options: SearchOptions, filePaths: string[]): Promise<string[]> =>
    ipcRenderer.invoke('fs:replace', query, replacement, options, filePaths),

  readConfig: (): Promise<GlobalConfig> =>
    ipcRenderer.invoke('config:read'),

  writeConfig: (updates: Partial<GlobalConfig>): Promise<void> =>
    ipcRenderer.invoke('config:write', updates),

  pickProjectFolder: (): Promise<string | null> =>
    ipcRenderer.invoke('config:pickFolder'),
})
