const { migrate } = require("./services/db");
const { ensureDefaults, getSetting, setSetting } = require("./services/settings");
const { createWebServer } = require("./web/server");
const { startBot, stopBot } = require("./services/discord");
const { startTwitchBot, stopTwitchBot } = require("./services/twitch");
const { startYouTubeBot, stopYouTubeBot } = require("./services/youtube");
const pluginService = require("./services/plugins");
const { loadEnabled } = pluginService;
const stopPlugins =
  typeof pluginService.stopPlugins === "function"
    ? pluginService.stopPlugins
    : async () => {};
const { checkForUpdates, completePendingBranchDeployment, pullUpdates, registerRestartHandler, requestRestart } = require("./services/updater");
const { createCommandRouter } = require("./services/command-router");
const { registerTopCommand } = require("./services/top");
const logger = require("./services/logger");
const { isPlatformEnabled } = require("./services/platforms");
const { registerCorePlaceholders } = require("./services/placeholders");
const { overlayConnectorManager } = require("./services/overlay-connectors");
const { cleanupSnapshots } = require("./services/update-manager");
const { twitchEventSubManager } = require("./services/twitch-eventsub");
const {
  isSafeModeRequested,
  markStartupVerification
} = require("./services/recovery-mode");

async function main() {
  migrate();
  ensureDefaults();
  const configuredRemote = getSetting("git_remote", "origin");
  const configuredBranch = getSetting("git_branch", "main");
  const completedDeployment = await completePendingBranchDeployment(configuredRemote, configuredBranch);
  if (completedDeployment) {
    console.log(`Completed deployment of ${completedDeployment.deployment.branch}; restarting with synchronized core and plugin code.`);
    requestRestart({ delayMs: 0 });
    return;
  }
  registerCorePlaceholders();
  logger.hookConsole();
  const runtimeLog = logger.createLogger("core:runtime", { category: "lifecycle" });
  const logCleanup = logger.cleanupLogs({
    maxAgeDays: getSetting("log_retention_days", logger.DEFAULT_MAX_AGE_DAYS),
    maxEntries: getSetting("log_retention_max_entries", logger.DEFAULT_MAX_ENTRIES)
  });
  runtimeLog.info("Lumi startup initiated", {
    version: require("../package.json").version,
    node: process.version,
    platform: process.platform,
    log_entries_removed: logCleanup.removed
  }, { event: "startup" });
  try {
    cleanupSnapshots();
  } catch (error) {
    console.warn(`Snapshot cleanup could not complete: ${error.message}`);
  }
  const safeModeRequested = isSafeModeRequested();
  const startupMarker = markStartupVerification();
  if (startupMarker?.status === "stale") {
    console.warn("Recovery marker detected from incomplete update; start with LUMI_SAFE_MODE=1 for recovery tools.");
  }

  const settingsApi = { getSetting, setSetting };
  const commandRouter = createCommandRouter({ settings: settingsApi });
  registerTopCommand({ commandRouter, settings: settingsApi });
  let discordClient = null;
  let twitchClient = null;
  let youtubeClient = null;

  if (!safeModeRequested && isPlatformEnabled("discord")) {
    try {
      discordClient = await startBot({ commandRouter });
    } catch (error) {
      console.error("Discord bot failed to start", error);
    }
  }

  if (!safeModeRequested && isPlatformEnabled("twitch")) {
    try {
      twitchClient = await startTwitchBot({ commandRouter });
    } catch (error) {
      console.error("Twitch bot failed to start", error);
    }
    try {
      await twitchEventSubManager.start();
    } catch (error) {
      console.error("Twitch event alerts failed to start", error);
    }
  }

  if (!safeModeRequested && isPlatformEnabled("youtube")) {
    try {
      youtubeClient = await startYouTubeBot({ commandRouter });
    } catch (error) {
      console.error("YouTube bot failed to start", error);
    }
  }

  const app = createWebServer({
    discordClient,
    commandRouter,
    loadPlugins: (appInstance, web, webhooks) => {
      if (safeModeRequested) return;
      loadEnabled({
        app: appInstance,
        discordClient,
        twitchClient,
        youtubeClient,
        settings: settingsApi,
        web,
        webhooks,
        commandRouter
      });
    }
  });

  if (!safeModeRequested) {
    overlayConnectorManager.start().catch((error) => {
      console.error("OBS overlay connectors failed to start", error);
    });
  }

  const port = Number(process.env.PORT || 3000);
  const webServer = app.listen(port, () => {
    runtimeLog.run({ event: "web_ready" }, () => {
      console.log(`WebUI listening on http://localhost:${port}`, { port });
    });
  });
  app.locals.lumiUpgradeRegistry?.attach(webServer);

  const autoUpdateEnabled = getSetting("auto_update_enabled", false);
  const intervalMinutes = getSetting("auto_update_interval_minutes", 60);
  if (!safeModeRequested && autoUpdateEnabled) {
    const intervalMs = Math.max(5, Number(intervalMinutes)) * 60 * 1000;
    let autoUpdateRunning = false;
    setInterval(async () => {
      if (autoUpdateRunning) return;
      autoUpdateRunning = true;
      try {
        const remote = getSetting("git_remote", "origin");
        const branch = getSetting("git_branch", "main");
        if (checkForUpdates(remote, branch)) {
          await pullUpdates(remote, branch);
          requestRestart();
        }
      } catch (error) {
        console.error("Auto-update failed", error);
      } finally {
        autoUpdateRunning = false;
      }
    }, intervalMs);
  }

  let shuttingDown = false;
  const shutdown = async (exitCode = 0) => {
    if (shuttingDown) {
      return;
    }
    shuttingDown = true;
    app.locals.lumiUpgradeRegistry?.close();
    runtimeLog.info("Lumi shutdown started", { exit_code: exitCode }, { event: exitCode === 10 ? "restart" : "shutdown" });
    const closeWebServer = new Promise((resolve) => webServer.close(resolve));
    for (const stop of [
      () => overlayConnectorManager.stop(),
      () => twitchEventSubManager.stop(),
      () => stopPlugins(),
      () => stopBot(),
      () => stopTwitchBot(),
      () => stopYouTubeBot()
    ]) {
      try {
        await stop();
      } catch (error) {
        runtimeLog.warn("A service did not stop cleanly", { error: error.message }, { event: "shutdown_service_error" });
      }
    }
    await Promise.race([
      closeWebServer,
      new Promise((resolve) => setTimeout(resolve, 2500))
    ]);
    webServer.closeAllConnections?.();
    process.exit(Number(exitCode) === 10 ? 10 : 0);
  };

  registerRestartHandler(() => shutdown(10));
  process.on("SIGINT", () => shutdown(0));
  process.on("SIGTERM", () => shutdown(0));
}

main();
