import { contextBridge, ipcRenderer } from 'electron'
import type { IpcRendererEvent } from 'electron'

function on<T>(channel: string, cb: (payload: T) => void): () => void {
  const listener = (_e: IpcRendererEvent, payload: T): void => cb(payload)
  ipcRenderer.on(channel, listener)
  return () => ipcRenderer.removeListener(channel, listener)
}

const api = {
  win: {
    minimize: (): void => ipcRenderer.send('win:minimize'),
    toggleMaximize: (): void => ipcRenderer.send('win:toggle-maximize'),
    close: (): void => ipcRenderer.send('win:close'),
    onMaximized: (cb: (v: boolean) => void): (() => void) => on('win:maximized', cb)
  },
  screens: {
    list: (): Promise<unknown[]> => ipcRenderer.invoke('screens:list'),
    states: (): Promise<unknown[]> => ipcRenderer.invoke('screens:states'),
    publish: (payload: { index: number; url: string; title: string }): Promise<unknown[]> =>
      ipcRenderer.invoke('screen:publish', payload),
    close: (index: number): Promise<unknown[]> => ipcRenderer.invoke('screen:close', index),
    closeAll: (): Promise<unknown[]> => ipcRenderer.invoke('screen:closeAll'),
    mainIndex: (): Promise<number> => ipcRenderer.invoke('screens:mainIndex'),
    publishMain: (payload: { url: string; title: string }): Promise<unknown[]> =>
      ipcRenderer.invoke('screen:publishMain', payload),
    restoreMain: (): Promise<unknown[]> => ipcRenderer.invoke('screen:restoreMain'),
    probe: (): Promise<unknown[]> => ipcRenderer.invoke('screens:probe'),
    keyLock: (locked: boolean): Promise<boolean> => ipcRenderer.invoke('screens:keyLock', locked),
    keyLockState: (): Promise<boolean> => ipcRenderer.invoke('screens:keyLockState'),
    onChanged: (cb: (list: unknown[]) => void): (() => void) => on('screens:changed', cb)
  },
  carousel: {
    start: (payload: { index: number; pages: { url: string; title: string }[]; intervalSec?: number }): Promise<unknown[]> =>
      ipcRenderer.invoke('carousel:start', payload),
    stop: (index: number): Promise<unknown[]> => ipcRenderer.invoke('carousel:stop', index)
  },
  project: {
    saveAs: (data: string, password?: string): Promise<string | null> =>
      ipcRenderer.invoke('project:saveAs', { data, password }),
    save: (path: string, data: string, password?: string): Promise<string | null> =>
      ipcRenderer.invoke('project:save', { path, data, password }),
    open: (password?: string): Promise<{ path: string; json: unknown | null; error?: string } | null> =>
      ipcRenderer.invoke('project:open', password),
    openAt: (path: string, password?: string): Promise<{ path: string; json: unknown | null; error?: string }> =>
      ipcRenderer.invoke('project:openAt', { path, password })
  },
  settings: {
    get: (): Promise<unknown> => ipcRenderer.invoke('settings:get'),
    set: (patch: unknown): Promise<unknown> => ipcRenderer.invoke('settings:set', patch)
  },
  shortcuts: {
    create: (kind: unknown): Promise<unknown> => ipcRenderer.invoke('shortcut:create', kind)
  },
  app: {
    info: (): Promise<unknown> => ipcRenderer.invoke('app:info'),
    consumeLoad: (): Promise<unknown> => ipcRenderer.invoke('app:consumeLoad'),
    onLoadProject: (cb: (payload: unknown) => void): (() => void) => on('app:loadProject', cb)
  },
  key: {
    onScreenKey: (cb: (n: number) => void): (() => void) => on('key:switch', cb)
  },
  page: {
    snapshot: (url: string): Promise<string | null> => ipcRenderer.invoke('page:snapshot', url)
  },
  syncProject: (pages: unknown[]): void => ipcRenderer.send('project:sync', pages),
  setDirty: (d: boolean): void => ipcRenderer.send('window:dirty', d),
  beep: (): Promise<void> => ipcRenderer.invoke('beep'),
  createShortcut: (): Promise<boolean> => ipcRenderer.invoke('desktop:shortcut'),
  confirm: (message: string): Promise<boolean> => ipcRenderer.invoke('dialog:confirm', message)
}

contextBridge.exposeInMainWorld('api', api)

export type Api = typeof api
