import type { Request, Response, NextFunction } from 'express';
import { env } from '../config/env.js';

const SESSION_COOKIE = 'docs_session';
const SESSION_TTL_MS = env.DOCS_SESSION_MINUTES * 60 * 1000;

// Express doesn't parse incoming cookies by default (that needs the
// cookie-parser package); this only ever needs to read one plain value,
// so it's hand-rolled instead of adding a dependency for it.
function readCookie(req: Request, name: string): string | undefined {
  const header = req.headers.cookie;
  if (!header) return undefined;
  const entry = header.split(';').map((part) => part.trim()).find((part) => part.startsWith(`${name}=`));
  return entry ? decodeURIComponent(entry.slice(name.length + 1)) : undefined;
}

function challenge(res: Response) {
  res.set('WWW-Authenticate', 'Basic realm="API Docs"');
  res.status(401).send('Authentication required');
}

// Protects /docs (Swagger UI) with plain HTTP Basic Auth — separate from the
// app's own Firebase auth, since this gates internal API documentation, not
// app user accounts. Once verified, a short-lived cookie avoids re-prompting
// on every request; it expires after DOCS_SESSION_MINUTES (default 10) and
// the browser has to re-authenticate.
export default function docsAuth(req: Request, res: Response, next: NextFunction) {
  const issuedAt = Number(readCookie(req, SESSION_COOKIE));
  if (Number.isFinite(issuedAt) && Date.now() - issuedAt < SESSION_TTL_MS) {
    return next();
  }

  const header = req.headers.authorization;
  if (!header?.startsWith('Basic ')) return challenge(res);

  const [username, password] = Buffer.from(header.slice('Basic '.length), 'base64').toString('utf-8').split(':');
  if (username !== env.DOCS_USERNAME || password !== env.DOCS_PASSWORD) return challenge(res);

  res.cookie(SESSION_COOKIE, String(Date.now()), {
    maxAge: SESSION_TTL_MS,
    httpOnly: true,
    sameSite: 'lax',
  });
  next();
}
