import { Request, Response, NextFunction } from 'express';
import { verifyAccessToken } from '../utils/jwt';
import { sendError } from '../utils/response';
import { ErrorCode } from '@saferoute/constants';
import { prisma } from '../config/database';

declare global {
  namespace Express {
    interface Request {
      user?: {
        userId: string;
        roles: string[];
        schoolIds: string[];
      };
    }
  }
}

export function authenticate(req: Request, res: Response, next: NextFunction): void {
  const authHeader = req.headers.authorization;

  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    sendError(res, ErrorCode.AUTH_TOKEN_EXPIRED, 'Authentication required. Please provide a valid Bearer token.', {}, 401);
    return;
  }

  const token = authHeader.substring(7);

  try {
    const payload = verifyAccessToken(token);

    req.user = {
      userId: payload.userId,
      roles: payload.roles,
      schoolIds: [],
    };

    next();
  } catch (error: any) {
    if (error.name === 'TokenExpiredError') {
      sendError(res, ErrorCode.AUTH_TOKEN_EXPIRED, 'Access token has expired. Please refresh your token.', {}, 401);
    } else {
      sendError(res, ErrorCode.AUTH_TOKEN_EXPIRED, 'Invalid access token.', {}, 401);
    }
  }
}

export async function loadSchoolScope(req: Request, _res: Response, next: NextFunction): Promise<void> {
  if (req.user) {
    const userRoles = await prisma.userRole.findMany({
      where: { userId: req.user.userId },
      select: { schoolId: true },
    });

    req.user.schoolIds = userRoles
      .filter((ur) => ur.schoolId !== null)
      .map((ur) => ur.schoolId as string);
  }

  next();
}
