/**
 * @fileoverview Utility module for codeValidations.js
 * 
 * @module games.cripto.config.codeValidations
 */

// Código de validações para prevenir loops infinitos e erros comuns nas fases do jogo.
// As validações são usadas pelo BaseGameScene/config.js para bloquear execuções inseguras.

/**
 * Valida se um loop while contém incremento ou decremento do contador
 * Previne loops infinitos onde o contador nunca muda
 */
export function validateWhileWithCounter(code) {
  // Verifica se há um loop while no código
  const hasWhile = /while\s*\(/i.test(code);
  if (!hasWhile) return { valid: true };

  // Verifica se o contador é usado na condição do while
  const whileWithCounter = /while\s*\([^)]*[cC]ontador[^)]*\)/i.test(code);
  if (!whileWithCounter) {
    // Se não usa contador na condição, não validamos (pode ser outro tipo de loop)
    return { valid: true };
  }

  // Verifica se há incremento/decremento do contador dentro do loop
  const hasCounterIncrement =
    /(definirContador|contador\s*[+-]=|\+\+contador|contador\+\+|--contador|contador--)/i.test(
      code,
    );

  if (!hasCounterIncrement) {
    return {
      valid: false,
      message:
        'Loop Infinito Detectado!\n\nSeu loop WHILE usa o CONTADOR na condição, mas não há incremento/decremento do CONTADOR dentro do loop.\n\nIsso causará um loop infinito!\n\nSolução: Adicione um bloco "definir CONTADOR" para incrementar o contador dentro do loop.',
    };
  }

  return { valid: true };
}

/**
 * Valida se o loop while tem uma condição que pode eventualmente se tornar falsa
 */
export function validateWhileCondition(code) {
  // Detecta condições sempre verdadeiras óbvias
  const alwaysTruePatterns = [
    /while\s*\(\s*true\s*\)/i,
    /while\s*\(\s*1\s*\)/i,
    /while\s*\(\s*"[^"]+"\s*\)/i, // string não vazia
  ];

  for (const pattern of alwaysTruePatterns) {
    if (pattern.test(code)) {
      return {
        valid: false,
        message:
          'Loop Infinito Detectado!\n\nSua condição do WHILE é sempre verdadeira, o que causará um loop infinito.\n\nSolução: Use uma condição que possa se tornar falsa, como "CONTADOR < comprimento de ENTRADA".',
      };
    }
  }

  return { valid: true };
}

/**
 * Valida se o loop while que usa length() modifica o que está sendo iterado
 */
export function validateWhileWithLength(code) {
  const hasWhileWithLength = /while\s*\([^)]*\.length[^)]*\)/i.test(code);
  if (!hasWhileWithLength) return { valid: true };

  // Verifica se há chamada para obterEntrada() dentro da condição
  const hasGetInputInCondition = /while\s*\([^)]*obterEntrada\(\)[^)]*\)/i.test(
    code,
  );
  if (!hasGetInputInCondition) return { valid: true };

  // Verifica se há incremento do contador
  const hasCounterIncrement =
    /(definirContador|contador\s*[+-]=|\+\+contador|contador\+\+)/i.test(
      code,
    );

  if (!hasCounterIncrement) {
    return {
      valid: false,
      message:
        "Loop Infinito Detectado!\n\nSeu loop usa o comprimento da ENTRADA, mas não incrementa o CONTADOR.\n\nIsso causará um loop infinito!\n\nSolução: Adicione incremento do CONTADOR dentro do loop.",
    };
  }

  return { valid: true };
}

/**
 * Valida se há pelo menos um loop no código (para fases que exigem iteração)
 */
export function validateHasLoop(code) {
  const hasLoop = /while\s*\(|for\s*\(/i.test(code);

  if (!hasLoop) {
    return {
      valid: false,
      message:
        "Loop Necessário!\n\nEsta fase requer que você use um loop (WHILE) para processar cada caractere da entrada.\n\nSolução: Use um bloco WHILE para percorrer a entrada caractere por caractere.",
    };
  }

  return { valid: true };
}

/**
 * Valida se o código define a entrada antes de usá-la
 */
export function validateInputBeforeUse(code) {
  const hasGetInput = /obterEntrada\(\)/i.test(code);
  if (!hasGetInput) return { valid: true }; // Não usa entrada, ok

  const hasSetInput = /definirEntrada\(/i.test(code);

  if (!hasSetInput) {
    return {
      valid: false,
      message:
        'Entrada não definida!\n\nVocê está tentando obter a ENTRADA sem defini-la primeiro.\n\nSolução: Use o bloco "definir ENTRADA" antes de usar "obter ENTRADA".',
    };
  }

  // Verifica ordem (definir antes de obter) - simplificado
  const setInputIndex = code.search(/definirEntrada\(/i);
  const getInputIndex = code.search(/obterEntrada\(\)/i);

  if (getInputIndex < setInputIndex) {
    return {
      valid: false,
      message:
        'Ordem incorreta!\n\nVocê está tentando obter a ENTRADA antes de defini-la.\n\nSolução: Mova o bloco "definir ENTRADA" para antes de "obter ENTRADA".',
    };
  }

  return { valid: true };
}

/**
 * Combina múltiplas validações
 */
export function validateCode(code, validations = []) {
  for (const validation of validations) {
    const result = validation(code);
    if (!result.valid) {
      return result;
    }
  }
  return { valid: true };
}

/**
 * Validações padrão para fases com loops
 */
export const defaultLoopValidations = [
  validateWhileCondition,
  validateWhileWithCounter,
  validateWhileWithLength,
  validateInputBeforeUse,
];

/**
 * Validações para fases que exigem loops
 */
export const requiredLoopValidations = [
  validateHasLoop,
  ...defaultLoopValidations,
];
