import { verifyAccessToken } from '../services/token.service.js'

/**
 * Fastify preHandler — verifies our JWT access token and attaches claims to request.auth.
 *
 * On success: request.auth = { userType, userId, sessionId }
 * On failure: returns 401 UNAUTHORIZED and short-circuits the handler.
 *
 * Future hook: if Valkey-based instant revocation is enabled, add a
 * SISMEMBER revoked_sessions <session_id> check here before accepting.
 */
export const authenticate = async (request, reply) => {
  const authHeader = request.headers.authorization
  if (!authHeader?.startsWith('Bearer ')) {
    return reply.code(401).send({
      success: false,
      error: { code: 'UNAUTHORIZED', message: 'Missing or invalid authorization header' },
    })
  }

  const token = authHeader.slice(7)
  try {
    const claims = verifyAccessToken(token)
    if (!claims.userId || !claims.userType || !claims.sessionId) {
      return reply.code(401).send({
        success: false,
        error: { code: 'UNAUTHORIZED', message: 'Invalid token claims' },
      })
    }
    request.auth = claims
  } catch (err) {
    return reply.code(err.statusCode || 401).send({
      success: false,
      error: { code: err.code || 'UNAUTHORIZED', message: err.message || 'Invalid or expired token' },
    })
  }
}

/**
 * Returns a preHandler that checks if the authenticated CC user has the required permission.
 * Requires `attachCcUser` (or equivalent) to have run earlier and set request.ccUser.
 * Usage: requirePermission('mitra', 'create')
 */
export const requirePermission = (resource, action) => {
  return async (request, reply) => {
    const permissions = request.ccUser?.role?.permissions ?? {}
    if (!permissions[resource]?.includes(action)) {
      return reply.code(403).send({
        success: false,
        error: { code: 'FORBIDDEN', message: 'Insufficient permissions' },
      })
    }
  }
}
