import { verifyToken } from '../services/token.service.js';
import prisma from '../services/prisma.js';
import ApiError from '../utils/ApiError.js';
import asyncHandler from '../utils/asyncHandler.js';

function extractToken(req) {
  const header = req.headers.authorization;
  if (header && header.startsWith('Bearer ')) {
    return header.slice(7);
  }
  if (req.cookies && req.cookies.token) {
    return req.cookies.token;
  }
  return null;
}

export const authenticate = asyncHandler(async (req, _res, next) => {
  const token = extractToken(req);
  if (!token) throw ApiError.unauthorized('Authentication required');

  let payload;
  try {
    payload = verifyToken(token);
  } catch {
    throw ApiError.unauthorized('Invalid or expired token');
  }

  const user = await prisma.user.findUnique({
    where: { id: payload.sub },
    select: { id: true, email: true, name: true, role: true, emailVerified: true },
  });
  if (!user) throw ApiError.unauthorized('User no longer exists');

  req.user = user;
  next();
});

// Optional auth: attaches req.user if a valid token is present, never throws.
export const optionalAuth = asyncHandler(async (req, _res, next) => {
  const token = extractToken(req);
  if (!token) return next();
  try {
    const payload = verifyToken(token);
    const user = await prisma.user.findUnique({
      where: { id: payload.sub },
      select: { id: true, email: true, name: true, role: true, emailVerified: true },
    });
    if (user) req.user = user;
  } catch {
    /* ignore */
  }
  next();
});

// Admin area: ADMIN manages everything except Users & Finance; SUPER_ADMIN can do all.
export const requireAdmin = (req, _res, next) => {
  if (!req.user) return next(ApiError.unauthorized());
  if (req.user.role !== 'ADMIN' && req.user.role !== 'SUPER_ADMIN') {
    return next(ApiError.forbidden('Admin access required'));
  }
  next();
};

// Restricted area (Users & Finance): SUPER_ADMIN only.
export const requireSuperAdmin = (req, _res, next) => {
  if (!req.user) return next(ApiError.unauthorized());
  if (req.user.role !== 'SUPER_ADMIN') {
    return next(ApiError.forbidden('Super admin access required'));
  }
  next();
};
