// Input validation
const isValidInput = (str: string): boolean => {
  if (!str) return false;
  const numbers = extractNumbers(str);
  return hasValidLength(numbers) && !hasRepeatingDigits(numbers);
};

// Extract only numbers from string
const extractNumbers = (str: string): string => 
  str.replace(/[^\d]/g, '');

// Validate CNPJ length
const hasValidLength = (numbers: string): boolean => 
  numbers.length === 14;

// Check for repeating digits
const hasRepeatingDigits = (numbers: string): boolean => 
  /^(\d)\1+$/.test(numbers);

// Calculate verification digit
const calculateVerificationDigit = (numbers: string, length: number, initialWeight: number): number => {
  let sum = 0;
  let weight = initialWeight;
  
  for (let i = 0; i < length; i++) {
    sum += parseInt(numbers.charAt(i)) * weight;
    weight = weight === 2 ? 9 : weight - 1;
  }
  
  return sum % 11 < 2 ? 0 : 11 - (sum % 11);
};

// Verify CNPJ digits
const hasValidVerificationDigits = (numbers: string): boolean => {
  const firstDigit = calculateVerificationDigit(numbers, 12, 5);
  const secondDigit = calculateVerificationDigit(numbers, 13, 6);
  
  return (
    parseInt(numbers.charAt(12)) === firstDigit &&
    parseInt(numbers.charAt(13)) === secondDigit
  );
};

export function isCNPJ(str: string): boolean {
  if (!isValidInput(str)) return false;
  const numbers = extractNumbers(str);
  return hasValidVerificationDigits(numbers);
}
