import { ipcMain } from 'electron';

import { ipcChannels, type IpcInvokeMap } from '../../shared/ipc/contracts';

type Handler<K extends keyof IpcInvokeMap> = (
  payload: IpcInvokeMap[K]['req'],
) => Promise<IpcInvokeMap[K]['res']> | IpcInvokeMap[K]['res'];

const handlers = new Map<string, (payload: unknown) => Promise<unknown>>();

let licenseAssert: (() => void) | undefined;

export function setLicenseAssert(fn: () => void): void {
  licenseAssert = fn;
}

function channelRequiresLicense(channel: string): boolean {
  if (channel.startsWith('license.')) return false;
  if (channel.startsWith('app.')) return false;
  if (channel === ipcChannels.windows.closeMultiWindow) return false;
  if (channel === ipcChannels.windows.closeSceneDescription) return false;
  if (channel === ipcChannels.windows.closeMaterials) return false;
  if (channel === ipcChannels.windows.closeNpcs) return false;
  if (channel === ipcChannels.windows.closeNpcsEditor) return false;
  if (channel === ipcChannels.windows.togglePresentationFullscreen) return false;
  // Список файлов в %userData%/projects — только чтение; без лицензии список не должен «пропадать».
  if (channel === ipcChannels.project.list) return false;
  return true;
}

export function registerHandler<K extends keyof IpcInvokeMap>(channel: K, handler: Handler<K>) {
  const channelStr = channel as string;
  const wrap = channelRequiresLicense(channelStr);
  const inner = async (payload: unknown) => {
    if (wrap) {
      licenseAssert?.();
    }
    return handler(payload as IpcInvokeMap[K]['req']);
  };
  handlers.set(channelStr, inner);
}

export type IpcRegisterHandler = typeof registerHandler;

export function installIpcRouter(): void {
  for (const [channel, handler] of handlers.entries()) {
    ipcMain.handle(channel, async (_event, payload: unknown) => handler(payload));
  }
}
