// Admin Permission Middleware
// Checks permissions for admin console endpoints

import { Request, Response, NextFunction } from 'express';
import { AuthenticatedRequest } from './auth.middleware';
import { adminPermissionsService } from '@/core/admin/shared/admin-permissions.service';
import { AdminPermission } from '@/core/admin/shared/permissions.constants';
import { DbisError, ErrorCode } from '@/shared/types';

/**
 * Middleware to check admin permission
 */
export function requireAdminPermission(permission: AdminPermission) {
  return async (req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> => {
    try {
      const employeeId = req.employeeId;
      if (!employeeId) {
        throw new DbisError(
          ErrorCode.UNAUTHORIZED,
          'Employee identity required for admin operations'
        );
      }

      // Check permission
      const hasPermission = await adminPermissionsService.hasPermission(employeeId, permission);
      if (!hasPermission) {
        throw new DbisError(
          ErrorCode.FORBIDDEN,
          `Insufficient permissions: ${permission}`
        );
      }

      // Store permission in request for downstream use
      req.adminPermission = permission;
      next();
    } catch (error) {
      if (error instanceof DbisError) {
        res.status(error.code === ErrorCode.FORBIDDEN ? 403 : 401).json({
          success: false,
          error: {
            code: error.code,
            message: error.message,
          },
          timestamp: new Date(),
        });
        return;
      } else {
        res.status(500).json({
          success: false,
          error: {
            code: ErrorCode.INTERNAL_ERROR,
            message: 'Permission check failed',
          },
          timestamp: new Date(),
        });
        return;
      }
    }
  };
}

/**
 * Middleware to check if user can act on specific SCB
 */
export function requireSCBAccess(targetSCBIdParam: string = 'scbId') {
  return async (req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> => {
    try {
      const employeeId = req.employeeId;
      if (!employeeId) {
        throw new DbisError(
          ErrorCode.UNAUTHORIZED,
          'Employee identity required'
        );
      }

      const targetSCBId = req.params[targetSCBIdParam] || req.body.scbId;
      const employeeSCBId = req.sovereignBankId;

      const canAct = await adminPermissionsService.canActOnSCB(
        employeeId,
        targetSCBId,
        employeeSCBId
      );

      if (!canAct) {
        throw new DbisError(
          ErrorCode.FORBIDDEN,
          'Cannot perform action on this SCB'
        );
      }

      next();
    } catch (error) {
      if (error instanceof DbisError) {
        res.status(error.code === ErrorCode.FORBIDDEN ? 403 : 401).json({
          success: false,
          error: {
            code: error.code,
            message: error.message,
          },
          timestamp: new Date(),
        });
        return;
      } else {
        res.status(500).json({
          success: false,
          error: {
            code: ErrorCode.INTERNAL_ERROR,
            message: 'SCB access check failed',
          },
          timestamp: new Date(),
        });
        return;
      }
    }
  };
}

// Extend AuthenticatedRequest to include admin permission
declare module './auth.middleware' {
  interface AuthenticatedRequest {
    adminPermission?: AdminPermission;
  }
}

/** Default admin gate for IRU routes that import this symbol (see requireAdminPermission for specific checks). */
export const adminPermissionMiddleware = requireAdminPermission(AdminPermission.VIEW_GLOBAL_OVERVIEW);
