import type { Request, Response, NextFunction } from 'express';
import type { EventerSession, TeamDirectory } from './types';
import { verifySessionToken } from './session';

declare global {
  // eslint-disable-next-line @typescript-eslint/no-namespace
  namespace Express {
    interface Request {
      eventerSession?: EventerSession & { teams: string[] };
    }
  }
}

export function requireOidcSession(cookieName: string, secret: Uint8Array, loginPath: string) {
  return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    const token = req.cookies?.[cookieName];
    const session = token ? await verifySessionToken(token, secret) : null;
    if (!session) {
      res.redirect(loginPath);
      return;
    }
    req.eventerSession = { ...session, teams: [] };
    next();
  };
}

export function requireTeamAccess(teamDirectory: TeamDirectory, candidateTeams: string[]) {
  return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    if (!req.eventerSession) {
      res.status(500).json({ status: 'error', error: 'session_middleware_not_run' });
      return;
    }
    let teams: string[];
    try {
      teams = await teamDirectory.getTeamsForUser(req.eventerSession.username, candidateTeams);
    } catch {
      res.status(500).json({
        status: 'error',
        error: 'team_check_failed',
        message: 'Could not verify team access right now. Please try again shortly.',
      });
      return;
    }
    if (teams.length === 0) {
      res.status(403).json({
        status: 'error',
        error: 'team_access_required',
        message: 'Your account is not on the progcom allowlist. Contact the VP (chair of Programme Committee) to be added.',
      });
      return;
    }
    req.eventerSession.teams = teams;
    next();
  };
}
