import { BrowserWindow } from "electron";
import * as path from "path";
import { WindowGeometry } from "../../types";
import { createLogger } from "../../logger";

const logger = createLogger("main:overlay-window");

export type OverlayWindowKind = "visible" | "invisible";

export function updateOverlayWindowBoundsService(
  geometry: WindowGeometry,
  window: BrowserWindow | null,
): void {
  if (!geometry || !window || window.isDestroyed()) return;
  window.setBounds({
    x: geometry.x,
    y: geometry.y,
    width: geometry.width,
    height: geometry.height,
  });
}

export function ensureOverlayWindowLevelService(window: BrowserWindow): void {
  if (process.platform === "darwin") {
    window.setAlwaysOnTop(true, "screen-saver", 1);
    window.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
    window.setFullScreenable(false);
    return;
  }
  window.setAlwaysOnTop(true);
}

export function enforceOverlayLayerOrderService(options: {
  visibleOverlayVisible: boolean;
  invisibleOverlayVisible: boolean;
  mainWindow: BrowserWindow | null;
  invisibleWindow: BrowserWindow | null;
  ensureOverlayWindowLevel: (window: BrowserWindow) => void;
}): void {
  if (!options.visibleOverlayVisible || !options.invisibleOverlayVisible) return;
  if (!options.mainWindow || options.mainWindow.isDestroyed()) return;
  if (!options.invisibleWindow || options.invisibleWindow.isDestroyed()) return;

  options.ensureOverlayWindowLevel(options.mainWindow);
  options.mainWindow.moveTop();
}

export function createOverlayWindowService(
  kind: OverlayWindowKind,
  options: {
    isDev: boolean;
    overlayDebugVisualizationEnabled: boolean;
    ensureOverlayWindowLevel: (window: BrowserWindow) => void;
    onRuntimeOptionsChanged: () => void;
    setOverlayDebugVisualizationEnabled: (enabled: boolean) => void;
    isOverlayVisible: (kind: OverlayWindowKind) => boolean;
    tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean;
    onWindowClosed: (kind: OverlayWindowKind) => void;
  },
): BrowserWindow {
  const window = new BrowserWindow({
    show: false,
    width: 800,
    height: 600,
    x: 0,
    y: 0,
    transparent: true,
    frame: false,
    alwaysOnTop: true,
    skipTaskbar: true,
    resizable: false,
    hasShadow: false,
    focusable: true,
    webPreferences: {
      preload: path.join(__dirname, "..", "..", "preload.js"),
      contextIsolation: true,
      nodeIntegration: false,
      webSecurity: true,
      additionalArguments: [`--overlay-layer=${kind}`],
    },
  });

  options.ensureOverlayWindowLevel(window);

  const htmlPath = path.join(__dirname, "..", "..", "renderer", "index.html");

  window
    .loadFile(htmlPath, {
      query: { layer: kind === "visible" ? "visible" : "invisible" },
    })
    .catch((err) => {
      logger.error("Failed to load HTML file:", err);
    });

  window.webContents.on(
    "did-fail-load",
    (_event, errorCode, errorDescription, validatedURL) => {
      logger.error(
        "Page failed to load:",
        errorCode,
        errorDescription,
        validatedURL,
      );
    },
  );

  window.webContents.on("did-finish-load", () => {
    options.onRuntimeOptionsChanged();
    window.webContents.send(
      "overlay-debug-visualization:set",
      options.overlayDebugVisualizationEnabled,
    );
  });

  if (kind === "visible") {
    window.webContents.on("devtools-opened", () => {
      options.setOverlayDebugVisualizationEnabled(true);
    });
    window.webContents.on("devtools-closed", () => {
      options.setOverlayDebugVisualizationEnabled(false);
    });
  }

  window.webContents.on("before-input-event", (event, input) => {
    if (!options.isOverlayVisible(kind)) return;
    if (!options.tryHandleOverlayShortcutLocalFallback(input)) return;
    event.preventDefault();
  });

  window.hide();

  window.on("closed", () => {
    options.onWindowClosed(kind);
  });

  window.on("blur", () => {
    if (!window.isDestroyed()) {
      options.ensureOverlayWindowLevel(window);
    }
  });

  if (options.isDev && kind === "visible") {
    window.webContents.openDevTools({ mode: "detach" });
  }

  return window;
}
