import process from "node:process";

import { runtimeConfig } from "../config/runtime.js";
import { runDatabaseMigrations } from "../db/migrate.js";
import { ensureAdminUsersBootstrapped } from "../services/admin/admin-auth-service.js";
import { ensureFulfillmentCatalogBootstrapped } from "../services/bootstrap/fulfillment-bootstrap-service.js";
import { startScheduledJobs } from "../services/scheduler/scheduler-service.js";
import { warmupOcrService } from "../services/session/ocr.js";
import { warmupTencentBrowser } from "../services/session/session.js";
import { logError, logInfo, logWarn } from "../utils/logger.js";
import { formatStartupError, type StartupState } from "./state.js";

const CORE_BOOT_RETRY_DELAY_MS = 5_000;

export async function bootstrapCoreServices(
  startupState: StartupState,
  isShutdownStarted: () => boolean
) {
  if (startupState.core.running || isShutdownStarted()) {
    return;
  }

  startupState.core.running = true;

  while (!isShutdownStarted() && !startupState.core.ready) {
    startupState.phase = startupState.core.attemptCount === 0 ? "starting" : "retrying";
    startupState.core.attemptCount += 1;
    startupState.core.lastAttemptAt = new Date().toISOString();

    try {
      logInfo("[startup]", "开始执行核心启动步骤", {
        attempt: startupState.core.attemptCount,
      });

      await runDatabaseMigrations();
      await ensureFulfillmentCatalogBootstrapped();
      await ensureAdminUsersBootstrapped();

      startupState.core.ready = true;
      startupState.core.lastError = "";
      startupState.phase = "ready";
      startupState.core.readyAt = new Date().toISOString();

      logInfo("[startup]", "核心启动步骤完成，服务已就绪", {
        attempt: startupState.core.attemptCount,
      });

      startScheduledJobs();
      void bootstrapBrowser(startupState);
      void bootstrapOcr(startupState);
      break;
    } catch (error) {
      const message = formatStartupError(error);
      startupState.phase = "retrying";
      startupState.core.lastError = message;
      logError("[startup]", "核心启动步骤失败，将自动重试", {
        attempt: startupState.core.attemptCount,
        retryDelayMs: CORE_BOOT_RETRY_DELAY_MS,
        error,
      });

      await sleep(CORE_BOOT_RETRY_DELAY_MS);
    }
  }

  startupState.core.running = false;
}

async function bootstrapBrowser(startupState: StartupState) {
  startupState.browser.status = "starting";
  startupState.browser.lastAttemptAt = new Date().toISOString();

  try {
    const result = await warmupTencentBrowser();

    if (!result.warmed) {
      startupState.browser.status = "skipped";
      startupState.browser.message = "browser prewarm skipped";
      logInfo("[startup]", "browser prewarm skipped");
      return;
    }

    startupState.browser.status = "ready";
    startupState.browser.message = "browser prewarm ready";
    logInfo("[startup]", "browser prewarm ready");
  } catch (error) {
    if (isMissingPlaywrightBrowserError(error)) {
      const installCommand = resolveBrowserInstallCommand();
      startupState.browser.status = "degraded";
      startupState.browser.message = formatErrorMessage(error);
      logWarn("[startup]", `browser prewarm skipped: ${formatErrorMessage(error)}`);
      logWarn("[startup]", `请先安装浏览器依赖: ${installCommand}`);

      if (String(runtimeConfig.browser.chromePath || "").trim()) {
        logWarn("[startup]", "当前设置了 CHROME_PATH，也请确认该路径指向的浏览器可执行文件真实存在");
      }

      return;
    }

    startupState.browser.status = "degraded";
    startupState.browser.message = formatStartupError(error);
    logError("[startup]", "browser prewarm failed", error);
  }
}

async function bootstrapOcr(startupState: StartupState) {
  startupState.ocr.status = "starting";
  startupState.ocr.lastAttemptAt = new Date().toISOString();

  try {
    await warmupOcrService();
    startupState.ocr.status = "ready";
    startupState.ocr.message = "OCR service ready";
    logInfo("[startup]", "OCR service ready");
  } catch (error) {
    startupState.ocr.status = "degraded";
    startupState.ocr.message = formatStartupError(error);
    logWarn("[startup]", `OCR service skipped: ${formatStartupError(error)}`);
  }
}

function isMissingPlaywrightBrowserError(error: unknown) {
  const message = formatErrorMessage(error).toLowerCase();

  return (
    message.includes("executable doesn't exist") ||
    message.includes("please run the following command to download new browsers") ||
    (message.includes("browserType.launch".toLowerCase()) &&
      message.includes("please run"))
  );
}

function formatErrorMessage(error: unknown) {
  if (error instanceof Error && error.message) {
    return error.message.split("\n")[0].trim();
  }

  return String(error || "未知错误").trim();
}

function resolveBrowserInstallCommand() {
  if (process.platform === "linux") {
    return "npm run browser:install:linux";
  }

  return "npm run browser:install";
}

function sleep(ms: number) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}
