import express from "express";
import cors from "cors";
import cookieParser from "cookie-parser";
import dotenv from "dotenv";
import { randomUUID } from "node:crypto";

dotenv.config();

const PORT = Number(process.env.PORT || 7000);
const COOKIE_NAME = process.env.COOKIE_NAME || "sid";
const COOKIE_DOMAIN = process.env.COOKIE_DOMAIN || undefined; // e.g. your.dev.local
const COOKIE_SECURE = String(process.env.COOKIE_SECURE || "false") === "true"; // true for https
const COOKIE_SAMESITE = (process.env.COOKIE_SAMESITE || "lax") as
  | "lax"
  | "strict"
  | "none";
const ALLOWED_ORIGINS = (process.env.ALLOWED_ORIGINS || "http://localhost:5173,http://localhost:6006")
  .split(",")
  .map((s) => s.trim())
  .filter(Boolean);
const EXPOSE_TOKEN = String(process.env.EXPOSE_TOKEN || "true") !== "false"; // if false, GET won't return raw token

// In-memory store: sid -> token
const store = new Map<string, { token: string; updatedAt: number }>();

const app = express();

app.use(
  cors({
    origin(origin, cb) {
      if (!origin) return cb(null, true); // allow same-origin or curl
      if (ALLOWED_ORIGINS.includes(origin)) return cb(null, true);
      return cb(new Error("Not allowed by CORS"));
    },
    credentials: true,
  })
);
app.use(cookieParser());
app.use(express.json());

// Ensure a session cookie exists
app.use((req, res, next) => {
  let sid = req.cookies[COOKIE_NAME];
  if (!sid) {
    sid = randomUUID();
    res.cookie(COOKIE_NAME, sid, {
      httpOnly: true,
      sameSite: COOKIE_SAMESITE,
      secure: COOKIE_SECURE,
      domain: COOKIE_DOMAIN,
      path: "/",
      maxAge: 1000 * 60 * 60 * 24, // 1 day
    });
  }
  (req as any).sid = sid;
  next();
});

app.get("/health", (_req, res) => {
  res.json({ ok: true, service: "auth-gateway", port: PORT });
});

// Set token: accept JSON body { token } or Authorization: Bearer <token>
app.post("/auth/session", (req, res) => {
  const sid: string = (req as any).sid;
  const bearer = req.header("authorization") || req.header("Authorization");
  let token = req.body?.token as string | undefined;
  if (!token && bearer && bearer.toLowerCase().startsWith("bearer ")) {
    token = bearer.slice(7);
  }
  if (!token) {
    return res.status(400).json({ ok: false, error: "Missing token" });
  }
  store.set(sid, { token, updatedAt: Date.now() });
  res.json({ ok: true });
});

// Get token (if EXPOSE_TOKEN=true). Always returns session status.
app.get("/auth/session", (req, res) => {
  const sid: string = (req as any).sid;
  const item = store.get(sid);
  const data: any = { ok: true, exists: Boolean(item), updatedAt: item?.updatedAt ?? null };
  if (EXPOSE_TOKEN && item) data.token = item.token;
  res.json(data);
});

// Logout / clear token
app.delete("/auth/session", (req, res) => {
  const sid: string = (req as any).sid;
  store.delete(sid);
  // Optionally clear cookie
  res.clearCookie(COOKIE_NAME, {
    httpOnly: true,
    sameSite: COOKIE_SAMESITE,
    secure: COOKIE_SECURE,
    domain: COOKIE_DOMAIN,
    path: "/",
  });
  res.json({ ok: true });
});

app.listen(PORT, () => {
  // eslint-disable-next-line no-console
  console.log(`Auth gateway running on http://localhost:${PORT}`);
  // eslint-disable-next-line no-console
  console.log(`Allowed origins: ${ALLOWED_ORIGINS.join(", ")}`);
});