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

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

/**
 * Validador do jogo Quebra-Cabeças.
 * Implementa validações por fase para verificar entrada/saída esperadas.
 * @class PuzzleValidator
 * @extends BaseGameValidator
 */
export class PuzzleValidator extends BaseGameValidator {
  /**
   * Dispara a validação específica da fase configurada.
   * Usa `expectedOutput` declarado no config da fase para comparar
   * com o objeto montado pela cena. Retorna erro com mensagens
   * configuráveis em `gameConfig.mensagens`.
   * @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) {
    // se não houver referência à cena não dá para validar propriedades
    if (!sceneRef || typeof sceneRef.animalMontado !== "object") {
      return this.failure(
        gameConfig?.mensagens?.erroGeral ||
          "Não foi possível validar a solução."
      );
    }

    // tenta interpretar o expectedOutput como JSON
    let expected = {};
    try {
      if (config.expectedOutput) {
        expected = JSON.parse(config.expectedOutput);
      }
    } catch (e) {
      console.warn("expectedOutput inválido", e);
    }

    // compara cada par esperado com o animal montado
    const nomesPropriedades = {
      tipo: "Tipo", patas: "Patas", cobertura: "Cobertura",
      locomocao: "Locomoção", som: "Som",
    };

    // 1ª passagem: verifica se alguma propriedade obrigatória está ausente
    const ausentes = Object.keys(expected).filter((key) => {
      const montado = sceneRef.animalMontado[key];
      return montado === undefined || montado === null;
    });
    if (ausentes.length > 0) {
      const nomes = ausentes.map((k) => nomesPropriedades[k] || k).join(", ");
      return this.failure(
        gameConfig?.mensagens?.entradaIncorreta ||
          `Ainda faltam peças: ${nomes}. Certifique-se de adicionar todos os blocos necessários.`
      );
    }

    // 2ª passagem: verifica se algum valor está errado
    for (const [key, value] of Object.entries(expected)) {
      const montado = sceneRef.animalMontado[key];
      // converter ambos para string para não falhar por tipo (ex: 0 vs "0")
      if (String(montado) !== String(value)) {
        const nomeProp = nomesPropriedades[key] || key;
        return this.failure(
          `A peça "${nomeProp}" está errada! Você colocou "${montado}" — verifique e tente novamente.`
        );
      }
    }

    // passou em todas as checagens
    return this.success();
  }
}

/**
 * Função exportada para validação de soluções do jogo Quebra-Cabeças.
 * @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 PuzzleValidator();
  return validator.validatePhase(history, config, gameConfig, sceneRef);
}
