import express from "express";
import process from "node:process";

import adminRouter from "./routes/admin.js";
import claimsRouter from "./routes/claims.js";
import open91Router from "./routes/open-91.js";
import tencentRouter from "./routes/tencent.js";
import webhooksRouter from "./routes/webhooks.js";
import { buildSuccessPayload } from "./utils/http.js";
import { accessLogMiddleware } from "./middleware/access-log.js";
import { corsMiddleware } from "./middleware/cors.js";
import { buildHealthPayload, type StartupState } from "./startup/state.js";

type CreateAppOptions = {
  startupState: StartupState;
  isShutdownStarted: () => boolean;
};

export function createApp({ startupState, isShutdownStarted }: CreateAppOptions) {
  const app = express();

  app.use(accessLogMiddleware);
  app.use(corsMiddleware);
  app.use(express.json({ limit: "2mb" }));
  app.use(express.urlencoded({ extended: true }));

  app.get("/health", (_req, res) => {
    res.json(
      buildSuccessPayload(
        buildHealthPayload(startupState, isShutdownStarted()),
        startupState.core.ready ? "ready" : "starting"
      )
    );
  });

  app.get("/health/live", (_req, res) => {
    res.json(
      buildSuccessPayload({
        status: isShutdownStarted() ? "shutting_down" : "alive",
        pid: process.pid,
      })
    );
  });

  app.get("/health/ready", (_req, res) => {
    if (startupState.core.ready) {
      res.json(buildSuccessPayload(buildHealthPayload(startupState, isShutdownStarted()), "ready"));
      return;
    }

    res.status(503).json({
      code: 1,
      msg: startupState.core.lastError || "服务启动中，请稍后重试",
      errorCode: "service_not_ready",
      time: Math.floor(Date.now() / 1000),
      data: buildHealthPayload(startupState, isShutdownStarted()),
    });
  });

  app.use((req, res, next) => {
    if (startupState.core.ready) {
      next();
      return;
    }

    res.status(503).json({
      code: 1,
      msg: startupState.core.lastError || "服务启动中，请稍后重试",
      errorCode: "service_not_ready",
      time: Math.floor(Date.now() / 1000),
      data: {
        startup: {
          phase: startupState.phase,
          attemptCount: startupState.core.attemptCount,
          lastAttemptAt: startupState.core.lastAttemptAt,
        },
      },
    });
  });

  app.use("/api/v1/tencent", tencentRouter);
  app.use("/api/v1/open/91", open91Router);
  app.use("/api/v1/webhooks", webhooksRouter);
  app.use("/api/v1/claim", claimsRouter);
  app.use("/api/v1/admin", adminRouter);

  return app;
}
