import express, { type Request, Response, NextFunction } from "express";
import { createServer } from "http";

// Prevent Baileys crypto/WebSocket errors from crashing the entire server
process.on("uncaughtException", (err: Error) => {
  const msg = err?.message || String(err);
  if (
    msg.includes("Unsupported state or unable to authenticate") ||
    msg.includes("aesDecryptGCM") ||
    msg.includes("decodeFrame") ||
    msg.includes("noise-handler") ||
    msg.includes("WebSocket") ||
    msg.includes("ECONNRESET") ||
    msg.includes("EPIPE")
  ) {
    console.warn("[baileys] Recovered from WebSocket/crypto error:", msg);
    return;
  }
  console.error("[uncaughtException] Fatal error:", err);
  process.exit(1);
});

process.on("unhandledRejection", (reason: unknown) => {
  const msg = (reason as Error)?.message || String(reason);
  if (
    msg.includes("Unsupported state or unable to authenticate") ||
    msg.includes("aesDecryptGCM") ||
    msg.includes("Connection Closed") ||
    msg.includes("ECONNRESET") ||
    msg.includes("EPIPE")
  ) {
    console.warn("[baileys] Recovered from unhandled rejection:", msg);
    return;
  }
  console.error("[unhandledRejection]:", reason);
});

const app = express();
const httpServer = createServer(app);

// Trust reverse proxy (Replit deployments run behind a proxy that sets X-Forwarded-Proto)
app.set("trust proxy", 1);

let isReady = false;

const loadingPageHtml = `<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="refresh" content="2">
<title>جاري التحميل...</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#f5f0ff,#fff,#f5f0ff);font-family:system-ui,-apple-system,sans-serif}
.container{text-align:center;padding:2rem}
.spinner{width:48px;height:48px;border:4px solid #e9e0ff;border-top-color:#6C28FF;border-radius:50%;animation:spin 0.8s linear infinite;margin:0 auto 1.5rem}
@keyframes spin{to{transform:rotate(360deg)}}
p{color:#6C28FF;font-size:1.1rem;font-weight:500}
</style>
</head>
<body>
<div class="container">
<div class="spinner"></div>
<p>جاري التحميل...</p>
</div>
</body>
</html>`;

app.use((req: Request, res: Response, next: NextFunction) => {
  if (isReady) return next();
  if (req.path.startsWith("/api")) return next();
  if (req.method !== "GET" && req.method !== "HEAD") return next();
  res.status(200).type("html").send(loadingPageHtml);
});

declare module "http" {
  interface IncomingMessage {
    rawBody: unknown;
  }
}

app.use(
  express.json({
    verify: (req, _res, buf) => {
      req.rawBody = buf;
    },
  }),
);

app.use(express.urlencoded({ extended: false }));

export function log(message: string, source = "express") {
  const formattedTime = new Date().toLocaleTimeString("en-US", {
    hour: "numeric",
    minute: "2-digit",
    second: "2-digit",
    hour12: true,
  });

  console.log(`${formattedTime} [${source}] ${message}`);
}

app.get("/api/health", (_req, res) => {
  res.json({ status: "ok", timestamp: new Date().toISOString() });
});

app.use((req, res, next) => {
  const start = Date.now();
  const path = req.path;
  let capturedJsonResponse: Record<string, any> | undefined = undefined;

  const originalResJson = res.json;
  res.json = function (bodyJson, ...args) {
    capturedJsonResponse = bodyJson;
    return originalResJson.apply(res, [bodyJson, ...args]);
  };

  res.on("finish", () => {
    const duration = Date.now() - start;
    if (path.startsWith("/api")) {
      let logLine = `${req.method} ${path} ${res.statusCode} in ${duration}ms`;
      if (capturedJsonResponse) {
        logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`;
      }

      log(logLine);
    }
  });

  next();
});

(async () => {
  log("Starting server initialization...");

  const port = parseInt(process.env.PORT || "5000", 10);
  httpServer.listen(
    {
      port,
      host: "0.0.0.0",
      reusePort: true,
    },
    () => {
      log(`serving on port ${port}`);
    },
  );

  try {
    const { registerRoutes } = await import("./routes");
    await registerRoutes(httpServer, app);
    log("Routes registered successfully.");
    const hasManagerSecret = !!(
      process.env.MANAGER_REDEMPTION_SECRET ||
      Object.entries(process.env).find(([k]) => k.startsWith("MANAGER_REDEMPTION"))?.[1]
    );
    log(`[Discount] MANAGER_REDEMPTION_SECRET: ${hasManagerSecret ? "✓ موجود" : "✗ غير موجود — توليد كود الخصم معطّل"}`);
  } catch (error) {
    console.error("WARNING: Failed to register routes:", error);
  }

  app.use((err: any, _req: Request, res: Response, next: NextFunction) => {
    const status = err.status || err.statusCode || 500;
    const message = err.message || "Internal Server Error";

    console.error("Internal Server Error:", err);

    if (res.headersSent) {
      return next(err);
    }

    return res.status(status).json({ message });
  });

  if (process.env.NODE_ENV === "production") {
    const { serveStatic } = await import("./static");
    serveStatic(app);
  } else {
    const { setupVite } = await import("./vite");
    await setupVite(httpServer, app);
  }

  isReady = true;
  log("Server initialization complete.");
})();
