// FILE: backend/src/index.js  (ESM) ไฟล์ฉบับ “Bearer-only”
// FILE: src/index.js  (ESM)
import fs from "node:fs";
import express from "express";
import cors from "cors";

import sql from "./db/index.js";
import healthRouter from "./routes/health.js";
import { authJwt } from "./middleware/authJwt.js";
import { loadPrincipalMw } from "./middleware/loadPrincipal.js";

// ROUTES
import authRoutes from "./routes/auth.js";
import lookupRoutes from "./routes/lookup.js";
import organizationsRoutes from "./routes/organizations.js";
import projectsRoutes from "./routes/projects.js";
import correspondencesRoutes from "./routes/correspondences.js";
import rfasRoutes from "./routes/rfas.js";
import drawingsRoutes from "./routes/drawings.js";
import transmittalsRoutes from "./routes/transmittals.js";
import contractsRoutes from "./routes/contracts.js";
import contractDwgRoutes from "./routes/contract_dwg.js";
import categoriesRoutes from "./routes/categories.js";
import volumesRoutes from "./routes/volumes.js";
import uploadsRoutes from "./routes/uploads.js";
import usersRoutes from "./routes/users.js";
import permissionsRoutes from "./routes/permissions.js";

const PORT = Number(process.env.PORT || 3001);
const NODE_ENV = process.env.NODE_ENV || "development";

const FRONTEND_ORIGIN =
  process.env.FRONTEND_ORIGIN || "https://lcbp3.np-dms.work";

const ALLOW_ORIGINS = [
  "http://localhost:3000",
  "http://127.0.0.1:3000",
  FRONTEND_ORIGIN,
  ...(process.env.CORS_ALLOWLIST
    ? process.env.CORS_ALLOWLIST.split(",").map((x) => x.trim()).filter(Boolean)
    : []),
].filter(Boolean);

const LOG_DIR = process.env.BACKEND_LOG_DIR || "/app/logs";
try {
  if (!fs.existsSync(LOG_DIR)) fs.mkdirSync(LOG_DIR, { recursive: true });
} catch (e) {
  console.warn("[WARN] Cannot ensure LOG_DIR:", LOG_DIR, e?.message);
}

const app = express();
app.set("trust proxy", 1);

// CORS: allow list
app.use(
  cors({
    origin(origin, cb) {
      if (!origin) return cb(null, true); // server-to-server / curl
      cb(null, ALLOW_ORIGINS.includes(origin));
    },
    credentials: false, // Bearer-only
    methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
    allowedHeaders: [
      "Content-Type",
      "Authorization",
      "X-Requested-With",
      "Accept",
      "Origin",
      "Referer",
      "User-Agent",
      "Cache-Control",
      "Pragma",
    ],
    exposedHeaders: ["Content-Disposition", "Content-Length"],
  })
);
app.options(
  "*",
  cors({
    origin(origin, cb) {
      if (!origin) return cb(null, true);
      cb(null, ALLOW_ORIGINS.includes(origin));
    },
    credentials: false,
  })
);

app.use(express.json({ limit: "10mb" }));
app.use(express.urlencoded({ extended: true, limit: "10mb" }));

// minimal access log
app.use((req, _res, next) => {
  console.log(`[REQ] ${req.method} ${req.originalUrl}`);
  next();
});

// health/info (เปิดทั้ง /health, /livez, /readyz, /info)
app.get("/health", async (_req, res) => {
  try {
    const [[{ now }]] = await sql.query("SELECT NOW() AS now");
    res.json({ status: "ok", db: "ok", now });
  } catch (e) {
    res.status(500).json({ status: "degraded", db: "fail", error: e?.message });
  }
});
app.get("/livez", (_req, res) => res.send("ok"));
app.get("/readyz", async (_req, res) => {
  try { await sql.query("SELECT 1"); res.send("ready"); }
  catch { res.status(500).send("not-ready"); }
});
app.get("/info", (_req, res) =>
  res.json({
    name: "dms-backend",
    env: NODE_ENV,
    version: process.env.APP_VERSION || "0.5.0",
    commit: process.env.GIT_COMMIT || undefined,
  })
);

// ---------- Public (no auth) ----------
app.use("/api", healthRouter);
app.use("/api/auth", authRoutes);

// ---------- Protected (Bearer + Principal) ----------
app.use("/api", authJwt(), loadPrincipalMw());

app.use("/api/lookup", lookupRoutes);
app.use("/api/organizations", organizationsRoutes);
app.use("/api/projects", projectsRoutes);
app.use("/api/correspondences", correspondencesRoutes);
app.use("/api/rfas", rfasRoutes);
app.use("/api/drawings", drawingsRoutes);
app.use("/api/transmittals", transmittalsRoutes);
app.use("/api/contracts", contractsRoutes);
app.use("/api/contract-dwg", contractDwgRoutes);
app.use("/api/categories", categoriesRoutes);
app.use("/api/volumes", volumesRoutes);
app.use("/api/uploads", uploadsRoutes);
app.use("/api/users", usersRoutes);
app.use("/api/permissions", permissionsRoutes);

// 404 / error
app.use((req, res) =>
  res.status(404).json({ error: "NOT_FOUND", path: req.originalUrl })
);
// eslint-disable-next-line no-unused-vars
app.use((err, _req, res, _next) => {
  console.error("[UNHANDLED ERROR]", err);
  res.status(err?.status || 500).json({ error: "SERVER_ERROR" });
});

// START
const server = app.listen(PORT, () => {
  console.log(`Backend API listening on ${PORT} (env=${NODE_ENV})`);
});

// Shutdown
async function shutdown(signal) {
  try {
    console.log(`[SHUTDOWN] ${signal} received`);
    await new Promise((resolve) => server.close(resolve));
    try { await sql.end(); } catch {}
    console.log("[SHUTDOWN] complete");
    process.exit(0);
  } catch (e) {
    console.error("[SHUTDOWN] error", e);
    process.exit(1);
  }
}
process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));

export default app;
