/**
 * Middleware to automatically mask sensitive company data in API responses
 */

import { Request, Response, NextFunction } from 'express';
import { transformCompanyForResponse, maskCompaniesData } from '@/shared/utils/maskingHelper';

/**
 * Recursively traverse an object and mask any company data found
 * @param obj - Object to traverse and mask
 * @returns Object with masked company data
 */
function maskCompanyDataInObject(obj: any): any {
  if (!obj || typeof obj !== 'object') {
    return obj;
  }

  if (Array.isArray(obj)) {
    return obj.map(item => maskCompanyDataInObject(item));
  }

  // Check if this object looks like a company object
  if (isCompanyObject(obj)) {
    return transformCompanyForResponse(obj);
  }

  // Recursively process nested objects
  const masked: any = {};
  for (const [key, value] of Object.entries(obj)) {
    if (key === 'company' && isCompanyObject(value)) {
      // Handle company field specifically
      masked[key] = transformCompanyForResponse(value);
    } else if (key === 'companies' && Array.isArray(value)) {
      // Handle companies array specifically
      masked[key] = maskCompaniesData(value);
    } else {
      masked[key] = maskCompanyDataInObject(value);
    }
  }

  return masked;
}

/**
 * Check if an object looks like a company object
 * @param obj - Object to check
 * @returns True if object appears to be a company object
 */
function isCompanyObject(obj: any): boolean {
  if (!obj || typeof obj !== 'object') {
    return false;
  }

  // Check for company-specific fields that indicate this is a company object
  const companyFields = [
    'companyType', 'gstNumber', 'websiteUrl', 'maxUserCount', 
    'planExpiryDate', 'myoperator', 'whatsapp', 'fast2sms'
  ];
  
  // If it has at least 2 company-specific fields, consider it a company object
  const matchingFields = companyFields.filter(field => obj.hasOwnProperty(field));
  return matchingFields.length >= 2;
}

/**
 * Middleware to automatically mask sensitive company data in responses
 * This should be applied globally or to specific routes that might return company data
 */
export function autoMaskCompanyData(req: Request, res: Response, next: NextFunction) {
  // Store the original json method
  const originalJson = res.json;

  // Override the json method to apply masking
  res.json = function(body: any) {
    // Apply masking to the response body
    const maskedBody = maskCompanyDataInObject(body);
    
    // Call the original json method with masked data
    return originalJson.call(this, maskedBody);
  };

  next();
}

/**
 * Utility function to manually mask company data in service responses
 * Use this in services that return company data directly
 * @param data - Data that might contain company objects
 * @returns Data with masked company information
 */
export function maskResponseData(data: any): any {
  return maskCompanyDataInObject(data);
}

export default autoMaskCompanyData;