/**
 * @fileoverview Utility module for validators.js
 * 
 * @module games.cripto.validation.validators
 */

import { BaseGameValidator } from "../../../../shared/BaseGameValidator";

/**
 * Validador do jogo Criptografia.
 * Implementa validações por fase para verificar entrada/saída esperadas.
 * @class CriptoValidator
 * @extends BaseGameValidator
 */
export class CriptoValidator extends BaseGameValidator {
  /**
   * Dispara a validação específica da fase configurada.
   * Delegates para `validateFase{n}` quando disponível.
   * @param {Array} history - Histórico de comandos
   * @param {Object} config - Configuração da fase
   * @param {Object} gameConfig - Configuração global do jogo
   * @param {Object} sceneRef - Referência à cena (opcional)
   * @returns {{success:boolean, reason?:string}}
   */
  validatePhase(history, config, gameConfig, sceneRef) {
    const phaseMethod = this[`validateFase${config.id}`];
    if (phaseMethod) {
      return phaseMethod.call(this, history, config, gameConfig, sceneRef);
    }

    return this.success();
  }

  /**
   * Validação da Fase 1: verifica entrada e saída esperadas.
   * @param {Array} history
   * @param {Object} config
   * @param {Object} gameConfig
   * @param {Object} sceneRef
   * @returns {{success:boolean, reason?:string}}
   */
  validateFase1(history, config, gameConfig, sceneRef) {
    const entradaEsperada = config.expectedInput;
    const saidaEsperada = config.expectedOutput;

    if (sceneRef.entrada !== entradaEsperada) {
      const mensagemBase =
        gameConfig?.mensagens?.entradaIncorreta ||
        "Entrada incorreta. Você deve definir a ENTRADA como o alfabeto completo.";

      return this.failure(
        `${mensagemBase}\n\nEsperado: "${entradaEsperada}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== saidaEsperada) {
      const mensagemBase =
        gameConfig?.mensagens?.saidaIncorreta ||
        "Saída incorreta. Cada letra deve ser convertida para sua posição numérica (A=0, B=1, C=2...). O CONTADOR já representa essa posição!";

      return this.failure(
        `${mensagemBase}\n\nEsperado: ${saidaEsperada}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 2: valida entrada/saída conforme esperado.
   */
  validateFase2(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Cada número deve ser convertido na letra correspondente do alfabeto.\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 3: deslocamento de letras.
   */
  validateFase3(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Cada letra deve ser deslocada 3 posições para a frente (A→D, B→E, Z→C).\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 4: inversão de deslocamento.
   */
  validateFase4(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Cada letra deve voltar 3 posições (D→A, E→B, C→Z).\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 5: usa chave de deslocamento fornecida.
   */
  validateFase5(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Use a chave ${config.chave} para deslocar cada letra.\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 6: descriptografia com chave.
   */
  validateFase6(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Volte ${config.chave} posições para descriptografar.\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 7: substituições específicas (ex: A→4).
   */
  validateFase7(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Substitua A→4 e E→3, mantendo as outras letras.\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 8: inverte a ordem das letras.
   */
  validateFase8(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Inverta a ordem das letras.\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 9: usa alfabeto secreto para substituição.
   */
  validateFase9(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Use o alfabeto secreto para substituir cada letra.\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }

  /**
   * Validação da Fase 10: soma posições das letras no alfabeto.
   */
  validateFase10(history, config, gameConfig, sceneRef) {
    if (sceneRef.entrada !== config.expectedInput) {
      return this.failure(
        `Entrada incorreta.\n\nEsperado: "${config.expectedInput}"\nRecebido: "${sceneRef.entrada}"`,
      );
    }

    if (sceneRef.saida !== config.expectedOutput) {
      return this.failure(
        `Saída incorreta. Some as posições de todas as letras no alfabeto.\n\nEsperado: ${config.expectedOutput}\nRecebido: ${sceneRef.saida}`,
      );
    }

    return this.success();
  }
}

/**
 * Função exportada para validação de soluções do jogo Criptografia.
 * @param {Array} history - Histórico de ações do usuário
 * @param {Object} config - Configuração da fase
 * @param {Object} gameConfig - Configuração global do jogo
 * @param {Object} sceneRef - Referência à cena (opcional)
 * @returns {{success:boolean, reason?:string}}
 */
export function validationSolution(history, config, gameConfig, sceneRef) {
  const validator = new CriptoValidator();
  return validator.validatePhase(history, config, gameConfig, sceneRef);
}
