import { app, BrowserWindow, Menu, nativeImage, ipcMain } from "electron";
import { join } from "path";
import { existsSync } from "fs";
import { setupTray } from "./tray";
import { setupIPC } from "./ipc";
import { setupUpdater } from "./updater";
import { checkSingleInstance, getWebUrl, getApiPath, isDev } from "./utils";

// ─── Constants ───────────────────────────────────
const WEB_PORT = 3000;
const API_PORT = 3001;
const APP_NAME = "eduplatform";

// ─── Single Instance Lock ────────────────────────
if (!checkSingleInstance()) {
  app.quit();
  process.exit(0);
}

// ─── State ───────────────────────────────────────
let mainWindow: BrowserWindow | null = null;
let apiProcess: ReturnType<typeof import("child_process").spawn> | null = null;

// ─── Create Window ───────────────────────────────
function createWindow(): BrowserWindow {
  const preloadPath = join(__dirname, "preload.js");

  const win = new BrowserWindow({
    title: APP_NAME,
    width: 1400,
    height: 900,
    minWidth: 800,
    minHeight: 600,
    show: false,
    icon: getIconPath(),
    webPreferences: {
      preload: preloadPath,
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: false,
    },
    titleBarStyle: process.platform === "darwin" ? "hiddenInset" : "default",
    trafficLightPosition: { x: 16, y: 16 },
  });

  // ── Load content ──
  const url = getWebUrl(isDev(), WEB_PORT);
  if (url.startsWith("http")) {
    win.loadURL(url);
  } else {
    win.loadFile(url);
  }

  // ── Show when ready ──
  win.once("ready-to-show", () => {
    win.show();
    if (isDev()) {
      win.webContents.openDevTools({ mode: "detach" });
    }
  });

  // ── External links → default browser ──
  win.webContents.setWindowOpenHandler(({ url }) => {
    if (url.startsWith("http")) {
      require("electron").shell.openExternal(url);
    }
    return { action: "deny" };
  });

  // ── Prevent navigation away ──
  win.webContents.on("will-navigate", (event, url) => {
    const allowed = isDev()
      ? url.startsWith("http://localhost:3000")
      : url.startsWith("file://");
    if (!allowed) event.preventDefault();
  });

  return win;
}

// ─── Icon Path ───────────────────────────────────
function getIconPath(): string {
  const candidates = [
    join(__dirname, "..", "assets", "icon.png"),
    join(__dirname, "..", "assets", "icon.icns"),
    join(__dirname, "..", "assets", "icon.ico"),
  ];
  for (const p of candidates) {
    if (existsSync(p)) return p;
  }
  return "";
}

// ─── API Server (Production) ─────────────────────
function startApiServer(): void {
  if (isDev()) return;

  const apiPath = getApiPath();
  if (!apiPath || !existsSync(apiPath)) {
    console.warn("[main] API server not found at", apiPath);
    return;
  }

  const { spawn } = require("child_process");
  apiProcess = spawn("node", [apiPath], {
    env: {
      ...process.env,
      NODE_ENV: "production",
      PORT: String(API_PORT),
      HOST: "127.0.0.1",
    },
    stdio: ["ignore", "pipe", "pipe"],
  });

  apiProcess!.stdout?.on("data", (data: Buffer) => {
    console.log("[api]", data.toString().trim());
  });
  apiProcess!.stderr?.on("data", (data: Buffer) => {
    console.error("[api]", data.toString().trim());
  });
  apiProcess!.on("exit", (code: number) => {
    console.warn("[main] API server exited with code", code);
    apiProcess = null;
  });
}

function stopApiServer(): void {
  if (apiProcess) {
    apiProcess.kill("SIGTERM");
    apiProcess = null;
  }
}

// ─── Menu ────────────────────────────────────────
function buildMenu(): void {
  const isMac = process.platform === "darwin";

  const template: Electron.MenuItemConstructorOptions[] = [
    ...(isMac
      ? [{
          label: APP_NAME,
          submenu: [
            { role: "about" as const },
            { type: "separator" as const },
            { role: "services" as const },
            { type: "separator" as const },
            { role: "hide" as const },
            { role: "hideOthers" as const },
            { role: "unhide" as const },
            { type: "separator" as const },
            { role: "quit" as const },
          ],
        }]
      : []),
    {
      label: "Edit",
      submenu: [
        { role: "undo" },
        { role: "redo" },
        { type: "separator" },
        { role: "cut" },
        { role: "copy" },
        { role: "paste" },
        { role: "selectAll" },
      ],
    },
    {
      label: "View",
      submenu: [
        { role: "reload" },
        { role: "forceReload" },
        { role: "toggleDevTools" },
        { type: "separator" },
        { role: "resetZoom" },
        { role: "zoomIn" },
        { role: "zoomOut" },
        { type: "separator" },
        { role: "togglefullscreen" },
      ],
    },
    {
      label: "Window",
      submenu: [
        { role: "minimize" },
        { role: "zoom" },
        ...(isMac
          ? [
              { type: "separator" as const },
              { role: "front" as const },
            ]
          : [{ role: "close" as const }]),
      ],
    },
  ];

  Menu.setApplicationMenu(Menu.buildFromTemplate(template));
}

// ─── App Lifecycle ───────────────────────────────
app.whenReady().then(() => {
  startApiServer();
  mainWindow = createWindow();
  buildMenu();
  if (mainWindow) {
    setupTray(mainWindow, APP_NAME);
    setupIPC(mainWindow);
  }
  setupUpdater(APP_NAME);

  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      mainWindow = createWindow();
      if (mainWindow) {
        setupTray(mainWindow, APP_NAME);
        setupIPC(mainWindow);
      }
    }
  });
});

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

app.on("before-quit", () => {
  stopApiServer();
});

app.on("gpu-process-crashed" as any, () => {
  console.warn("[main] GPU process crashed — continuing");
});

process.on("exit", () => {
  stopApiServer();
});
