// FFAI Agent Desktop —— Electron 主进程入口
//
// PR11 骨架 + PR12 Client Executor 工具家族真实化（fs / clipboard / notify）。
// Shell.exec (PR13) 暂走 dispatcher 内显式拒绝，等沙盒 PoC + 红队 25 case 0 逃逸过关。
//
// 详见 docs/modules/agent/02-architecture.md §1.3.2 / §1.1.1。

import { app, BrowserWindow, ipcMain, Tray, Menu } from "electron";
import * as path from "node:path";
import { initI18n, t } from "./i18n";
import { dispatchInvoke } from "./host-bridge/dispatcher";

const FRONTEND_URL = process.env.FFAI_FRONTEND_URL ?? "http://localhost:3000";

let mainWindow: BrowserWindow | null = null;
let tray: Tray | null = null;

function createMainWindow(): void {
  mainWindow = new BrowserWindow({
    width: 1440,
    height: 900,
    minWidth: 1024,
    minHeight: 640,
    title: t("app.title"),
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
    },
  });

  if (FRONTEND_URL.startsWith("file://")) {
    mainWindow.loadFile(FRONTEND_URL.replace("file://", ""));
  } else {
    void mainWindow.loadURL(FRONTEND_URL);
  }

  mainWindow.on("closed", () => {
    mainWindow = null;
  });
}

function createTray(): void {
  tray = new Tray(path.join(__dirname, "..", "assets", "tray-icon.png"));
  const menu = Menu.buildFromTemplate([
    { label: t("tray.open"), click: () => mainWindow?.show() },
    { type: "separator" },
    { label: t("tray.quit"), click: () => app.quit() },
  ]);
  tray.setContextMenu(menu);
  tray.setToolTip(t("tray.tooltip"));
}

// ───────────────────────────────────────────────────────────
// HostBridge IPC handlers（preload 暴露的 window.ffaiHostBridge → 这里 → dispatcher）
// ───────────────────────────────────────────────────────────

import type { HostCapability } from "@ffai/agent-protocol";

/**
 * Desktop Electron 上报的能力集 —— **三处镜像之一**，详见
 * `packages/agent-protocol/src/host-bridge.ts` 的 `DESKTOP_ELECTRON_CAPABILITIES` JSDoc。
 *
 * 此处就地声明而不 import：protocol 包是 ESM-only（"exports.import"），desktop tsconfig
 * 编 CJS，require 会撞 ERR_PACKAGE_PATH_NOT_EXPORTED（详见
 * `.learnings/2026-05-16-electron-mac-smoke-two-traps.md`）。PR15.5 monorepo workspace
 * 统一切回 import 后此局部常量删除。
 */
const DESKTOP_ELECTRON_CAPABILITIES: readonly HostCapability[] = [
  "fs.read",
  "fs.write",
  "fs.list",
  "clipboard.read",
  "clipboard.write",
  "notify",
  "shell.exec",
  "shell.openExternal",
];

ipcMain.handle("hostBridge:capabilities", (): readonly HostCapability[] => {
  return DESKTOP_ELECTRON_CAPABILITIES;
});

ipcMain.handle("hostBridge:invoke", (_evt, tool: string, args: unknown) =>
  dispatchInvoke(tool, args),
);

// ───────────────────────────────────────────────────────────
// App lifecycle
// ───────────────────────────────────────────────────────────

app
  .whenReady()
  .then(() => {
    initI18n();
    createMainWindow();
    try {
      createTray();
    } catch (err) {
      // Tray icon 缺失不致命，开发期允许跳过
      console.warn("[ffai-desktop] tray init skipped:", (err as Error).message);
    }

    app.on("activate", () => {
      if (BrowserWindow.getAllWindows().length === 0) createMainWindow();
    });
  })
  .catch((err) => {
    console.error("[ffai-desktop] startup failed:", err);
    app.quit();
  });

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") app.quit();
});
