import type { Request, Response, NextFunction } from 'express';
import type { ModuleKey } from '../config/access.js';
import { effectiveAccess, findSessionUser } from '../models/session.model.js';
import { errorResponse } from '../utils/response.js';

export interface TenantAccessRule {
  module?: ModuleKey;
  permission?: string;
}

// Use after `verifyFirebaseToken` on every tenant (organization-scoped) route.
// The organization always comes from the signed-in user, never from the request,
// and the rule is the same one the apps check: the organization subscribes to the
// module AND the user's effective permissions include the permission.
export default function tenantAccess(rule: TenantAccessRule = {}) {
  return async (req: Request, res: Response, next: NextFunction) => {
    try {
      if (!req.user) return void errorResponse(res, 'Authentication required', 401);
      const user = await findSessionUser(Number(req.user.sub));
      if (!user?.organization) {
        return void errorResponse(res, "This account isn't linked to an organization", 403);
      }
      const { permissions } = effectiveAccess(user);
      if (rule.module && !user.organization.moduleKeys.includes(rule.module)) {
        return void errorResponse(res, 'This module is not in your subscription', 403);
      }
      if (rule.permission && !permissions.includes(rule.permission)) {
        return void errorResponse(res, "You don't have permission to do that", 403);
      }
      req.tenant = { organizationId: user.organization.id, user, permissions };
      next();
    } catch (error) {
      next(error);
    }
  };
}
