import type { NextFunction, Response } from 'express';
import { query } from '../db.js';
import { publicUser, verifyAccessToken } from '../security.js';
import type { AuthedRequest, Role } from '../types.js';
import { fail } from '../utils/http.js';

export async function requireAuth(req: AuthedRequest, res: Response, next: NextFunction) {
  try {
    const header = req.headers.authorization;
    const token = header?.startsWith('Bearer ') ? header.slice(7) : undefined;
    if (!token) return fail(res, 401, 'UNAUTHORIZED', 'Authentication is required.');
    const claims = verifyAccessToken(token);
    const { rows } = await query(
      'SELECT id,name,email,phone,role,employee_code,force_password_change,token_version,is_active FROM users WHERE id=$1',
      [claims.sub]
    );
    const user = rows[0];
    if (!user || !user.is_active || Number(user.token_version) !== claims.tokenVersion) {
      return fail(res, 401, 'UNAUTHORIZED', 'Session is no longer valid.');
    }
    req.auth = publicUser(user);
    next();
  } catch {
    return fail(res, 401, 'UNAUTHORIZED', 'Invalid or expired session.');
  }
}

export function requireRoles(...roles: Role[]) {
  return (req: AuthedRequest, res: Response, next: NextFunction) => {
    if (!req.auth) return fail(res, 401, 'UNAUTHORIZED', 'Authentication is required.');
    if (!roles.includes(req.auth.role)) return fail(res, 403, 'FORBIDDEN', 'You do not have permission for this action.');
    next();
  };
}

export function requireNoForcedPasswordChange(req: AuthedRequest, res: Response, next: NextFunction) {
  if (req.auth?.forcePasswordChange) {
    return fail(res, 428, 'PASSWORD_CHANGE_REQUIRED', 'Change your password before using business modules.');
  }
  next();
}
