const path = require("path");
const { app, BrowserWindow, shell, session } = require("electron");

const APP_URL = "https://ovellan.com/chatbots";
const AUTH_ORIGIN = "https://ovellan.com";
const COOKIE_DOMAIN = ".ovellan.com";
const PROTOCOL = "ovellan";
const GOOGLE_START_PATH = "/api/auth/google/start";
const EXCHANGE_URL = "https://ovellan.com/api/auth/desktop/exchange";
// Google login for ovellan is bridged through the canonical auth host, so the desktop flag must be
// added when the sign-in starts there too — not only on ovellan hosts. Without this the browser
// logs in but never hands the one-time code back to the app.
const AUTH_HOST = "chat.astroworldmc.com";

let mainWindow = null;

// ovellan spans the apex plus the world subdomains (local./ecommerce.ovellan.com); all of them
// stay inside the app window. Everything else is "external" and opens in the system browser.
function isOvellanHost(hostname) {
  return hostname === "ovellan.com" || hostname.endsWith(".ovellan.com");
}

function isExternal(target) {
  try {
    return !isOvellanHost(new URL(target).hostname);
  } catch {
    return true;
  }
}

// Google sign-in must happen in the real system browser, never inside the app window.
// We open the start URL externally with a desktop flag; the web flow finishes in the browser
// and hands a one-time code back to the app over the custom protocol. The app never sees the
// Google password. Returns true if the navigation was handled (and should be cancelled).
function routeAuthExternally(target) {
  let u;
  try {
    u = new URL(target);
  } catch {
    return false;
  }
  if ((isOvellanHost(u.hostname) || u.hostname === AUTH_HOST) && u.pathname === GOOGLE_START_PATH) {
    u.searchParams.set("desktop", "1");
    shell.openExternal(u.toString());
    return true;
  }
  if (!isOvellanHost(u.hostname)) {
    shell.openExternal(target);
    return true;
  }
  return false;
}

async function handleDeepLink(url) {
  let code;
  try {
    code = new URL(url).searchParams.get("code");
  } catch {
    return;
  }
  if (!code) return;
  try {
    const res = await fetch(EXCHANGE_URL, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ code })
    });
    const data = await res.json().catch(() => null);
    if (!data || !data.ok || !data.token) return;
    await session.defaultSession.cookies.set({
      url: AUTH_ORIGIN,
      name: data.cookieName || "aw_chat_session",
      value: data.token,
      domain: COOKIE_DOMAIN,
      path: "/",
      secure: true,
      httpOnly: true,
      sameSite: "lax",
      expirationDate: Math.floor(Date.now() / 1000) + (data.maxAge || 2592000)
    });
    if (mainWindow) {
      mainWindow.loadURL(APP_URL);
      if (mainWindow.isMinimized()) mainWindow.restore();
      mainWindow.focus();
    }
  } catch {
    // Exchange failed; leave the user on the current screen to retry.
  }
}

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1280,
    height: 820,
    minWidth: 480,
    minHeight: 600,
    backgroundColor: "#f7f8fa",
    title: "ovellan",
    icon: path.join(__dirname, "build", "icon.png"),
    autoHideMenuBar: true,
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      contextIsolation: true,
      nodeIntegration: false,
      spellcheck: true
    }
  });

  mainWindow.loadURL(APP_URL);

  // New windows: send auth and any external link to the system browser.
  mainWindow.webContents.setWindowOpenHandler(({ url }) => {
    if (routeAuthExternally(url)) return { action: "deny" };
    if (isExternal(url)) {
      shell.openExternal(url);
      return { action: "deny" };
    }
    return { action: "allow" };
  });

  // Catch both direct navigations and server-side redirects (the Google start route 302s to
  // accounts.google.com, which fires will-redirect, not will-navigate).
  const onNav = (event, url) => {
    if (routeAuthExternally(url)) event.preventDefault();
  };
  mainWindow.webContents.on("will-navigate", onNav);
  mainWindow.webContents.on("will-redirect", onNav);

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

// Register the custom protocol so the system browser can hand the one-time code back to the app.
if (process.defaultApp) {
  if (process.argv.length >= 2) {
    app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, [path.resolve(process.argv[1])]);
  }
} else {
  app.setAsDefaultProtocolClient(PROTOCOL);
}

const gotLock = app.requestSingleInstanceLock();
if (!gotLock) {
  app.quit();
} else {
  // Windows and Linux deliver the deep link as a new process; forward it to the running instance.
  app.on("second-instance", (_event, argv) => {
    const deepLink = argv.find((arg) => arg.startsWith(`${PROTOCOL}://`));
    if (deepLink) handleDeepLink(deepLink);
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore();
      mainWindow.focus();
    }
  });

  // macOS delivers the deep link via open-url.
  app.on("open-url", (event, url) => {
    event.preventDefault();
    handleDeepLink(url);
  });

  app.whenReady().then(() => {
    createWindow();

    // First launch on Windows may carry the deep link in the initial argv.
    const initialDeepLink = process.argv.find((arg) => arg.startsWith(`${PROTOCOL}://`));
    if (initialDeepLink) handleDeepLink(initialDeepLink);

    if (app.isPackaged) {
      try {
        const { autoUpdater } = require("electron-updater");
        autoUpdater.autoDownload = true;
        autoUpdater.checkForUpdatesAndNotify().catch(() => {});
      } catch {
        // electron-updater unavailable; skip silently.
      }
    }

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

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