/**
 * @fileoverview Utility module for game.js
 * * @module games.puzzle.game
 */

import Phaser from "phaser";
import { BaseGameScene } from "../../../shared/BaseGameScene.js";
import { setupQuebraCabecasAPI } from "./hooks/interpreterSetup.js";
import { validationSolution } from "./validation/validators.js";
import { gameConfig } from "./config/config.js";
import { ConstantesJogo, ConstantesAssets, ConstantesSons } from "./ui/constants.js";
import { inicializarLayout } from "./ui/layout.js";
import { pulsarImagem, silhuetaTremendo, mostrarFeedback, iniciarLoopAnimais, pararLoopAnimais } from "./ui/animations.js";

class QuebraCabecasScene extends BaseGameScene {
  constructor() {
    super("QuebraCabecasScene");

    // Estado principal do jogo: armazena as propriedades escolhidas pelo aluno
    this.animalMontado = {};

    // Aqui você pode adicionar variáveis para guardar referências aos Sprites
    // ex: this.spriteCorpo = null; this.spritePatas = null;
  }

  /**
   * Inicializa a cena com dados opcionais passados pelo React/Router.
   * @param {Object} data - Dados de inicialização
   * @returns {void}
   */
  init(data) {
    super.init(data);
    this.limparVariaveis();
  }

  /**
   * Faz o preload dos recursos necessários.
   * @returns {void}
   */
  preload() {
    this.preloadGlobalAssets();
    
    const { CHAVES, PATHS } = ConstantesAssets;
  
    // Carrega os backgrounds
    this.load.image(CHAVES.BACKGROUND_1, PATHS.BACKGROUND_1);
    this.load.image(CHAVES.BACKGROUND_2, PATHS.BACKGROUND_2);
    this.load.image(CHAVES.BACKGROUND_3, PATHS.BACKGROUND_3);
    this.load.image(CHAVES.BACKGROUND_4, PATHS.BACKGROUND_4);

    // Carrega os animais
    const chavesAnimais = ['ABELHA', 'ARANHA', 'CACHORRO', 'CARACOL', 'COBRA', 'GATO', 'LEAO', 'PATO', 'PEIXE', 'SAPO'];
    chavesAnimais.forEach(animal => {
        this.load.image(CHAVES[animal], PATHS[animal]);
    });

    // Carrega os sons do puzzle
    const { CHAVES: SC, PATHS: SP } = ConstantesSons;
    this.load.audio(SC.BG, SP.BG);
    this.load.audio(SC.CACHORRO, SP.CACHORRO);
    this.load.audio(SC.GATO, SP.GATO);
    this.load.audio(SC.PATO, SP.PATO);
    this.load.audio(SC.LEAO, SP.LEAO);
    this.load.audio(SC.SAPO, SP.SAPO);
  }

  /**
   * Cria os elementos visuais e liga o interpretador JavaScript aos blocos.
   * @returns {void}
   */
  create() {
    // Liga o controlador base com a nossa API customizada e o validador
    this.setupStandardController(
      () => setupQuebraCabecasAPI(this, { animationSpeed: 100 }),
      (historico) => validationSolution(historico, this.configFase, gameConfig, this),
    );

    // Inicialização da interface
    const layout = inicializarLayout(this);
    this.layout = layout;
  }

  /**
   * Hook da BaseGameScene: chamado exatamente antes de rodar o código do aluno.
   * @returns {void}
   */
  onBeforeRun() {
    this.historico = [];
    this.limparVariaveis();
    this.playAudio(ConstantesSons.CHAVES.BG, { loop: true, volume: 0.3 });

    // Loop visual de todos os animais enquanto o aluno executa o código
    const keys = ['ABELHA', 'ARANHA', 'CACHORRO', 'CARACOL', 'COBRA', 'GATO', 'LEAO', 'PATO', 'PEIXE', 'SAPO']
      .map(k => ConstantesAssets.CHAVES[k]);
    iniciarLoopAnimais(this, keys, this._centroX(), this._centroY());
  }

  /**
   * Hook da BaseGameScene: chamado quando o aluno clica em "Resetar" ou cancela.
   * Para o som de background imediatamente.
   * @returns {void}
   */
  onReset() {
    this.stopAudio(ConstantesSons.CHAVES.BG);
    pararLoopAnimais(this);
    this.limparVariaveis();
    if (this.imagemChave) {
      this.imagemChave.destroy();
      this.imagemChave = null;
    }
  }

  /**
   * Reseta o objeto do animal e limpa os sprites da tela.
   * @returns {void}
   */
  limparVariaveis() {
    this.animalMontado = {};
    this.historico = [];
    if (this.imagemChave) {
      this.imagemChave.destroy();
      this.imagemChave = null;
    }
    if (this._textoFeedback) {
      this._textoFeedback.destroy();
      this._textoFeedback = null;
    }
  }

  // ---------------------------------------------------------------------------
  // Helpers
  // ---------------------------------------------------------------------------

  _centroX() { return this.layout?.centroX ?? ConstantesJogo.LARGURA_TELA / 2; }
  _centroY() { return this.layout?.centroY ?? ConstantesJogo.ALTURA_TELA / 2; }
  _topoY()   { return 30; }

  /**
   * Converte chave/valor do bloco numa frase natural para exibição.
   * @param {string} chave - nome da propriedade (tipo, patas, cobertura, locomocao, som)
   * @param {string|number} valor - valor seleccionado no bloco
   * @returns {string}
   */
  _mensagemNatural(chave, valor) {
    const TIPO = {
      mamifero:  "É um MAMÍFERO!",
      ave:       "É uma AVE!",
      reptil:    "É um RÉPTIL!",
      anfibio:   "É um ANFÍBIO!",
      peixe:     "É um PEIXE!",
      inseto:    "É um INSETO!",
      aracnideo: "É um ARACNÍDEO!",
      molusco:   "É um MOLUSCO!",
    };
    const LOCOMOCAO = {
      Anda:    "Ele ANDA!",
      Voa:     "Ele VOA!",
      Nada:    "Ele NADA!",
      Rasteja: "Ele RASTEJA!",
      Pula:    "Ele PULA!",
    };
    const SOM = {
      Miau:      "Ele MIA!",
      Auau:      "Ele LATE!",
      Quack:     "Ele GRASNA!",
      Zumbido:   "Ele ZUMBE!",
      Rugido:    "Ele RUGE!",
      Coaxado:   "Ele COAXA!",
      Silencioso:"Não emite sons!",
    };

    if (chave === "tipo")      return TIPO[valor]      ?? `É um ${String(valor).toUpperCase()}!`;
    if (chave === "patas")     return String(valor) === "0" ? "Não tem patas!" : `Tem ${valor} patas!`;
    if (chave === "cobertura") return `Tem ${String(valor).toUpperCase()}!`;
    if (chave === "locomocao") return LOCOMOCAO[valor] ?? `Ele ${String(valor).toUpperCase()}!`;
    if (chave === "som")       return SOM[valor]       ?? `Ele ${String(valor).toUpperCase()}!`;
    return `${chave}: ${valor}`;
  }

  // ---------------------------------------------------------------------------
  // API chamada pelo interpretador
  // ---------------------------------------------------------------------------

  /**
   * Salva o tipo "Pai" do animal e exibe feedback visual temporário (1s).
   * Assíncrono: o interpretador aguarda a Promise antes de continuar.
   * @param {string} tipoValor - mamifero, ave, reptil, etc.
   * @returns {Promise<void>}
   */
  async definirTipoAnimal(tipoValor) {
    this.animalMontado["tipo"] = tipoValor;
    this.historico.push({ tipo: "criar_animal", valor: tipoValor });
    await mostrarFeedback(this, this._mensagemNatural("tipo", tipoValor), this._centroX(), this._topoY());
  }

  /**
   * Registra uma característica do animal e exibe feedback visual temporário (1s).
   * Assíncrono: o interpretador aguarda a Promise antes de continuar.
   * @param {string} chave - A propriedade (ex: "patas", "cobertura")
   * @param {string|number} valor - O valor selecionado no combo (ex: 4, "pelo")
   * @returns {Promise<void>}
   */
  async definirCaracteristica(chave, valor) {
    this.animalMontado[chave] = valor;
    this.historico.push({ tipo: "definir_caracteristica", chave: chave, valor: valor });

    // Toca o som correspondente ao valor, se for o bloco de som
    if (chave === "som") {
      const chaveSom = ConstantesSons.BLOCO_PARA_CHAVE[valor];
      if (chaveSom) this.playAudio(chaveSom);
    }

    await mostrarFeedback(this, this._mensagemNatural(chave, valor), this._centroX(), this._topoY());
  }

  // ---------------------------------------------------------------------------
  // Hooks de resultado
  // ---------------------------------------------------------------------------

  /**
   * Hook async: BaseGameScene aguarda esta Promise antes de disparar gameSuccess().
   * Para o background, exibe a imagem do animal com efeito Pulsar.
   * @returns {Promise<void>}
   */
  async onSuccess() {
    this.stopAudio(ConstantesSons.CHAVES.BG);
    await pararLoopAnimais(this);
    const chave = this.configFase?.chave;
    if (chave && ConstantesAssets.CHAVES[chave]) {
      if (this.imagemChave) { this.imagemChave.destroy(); this.imagemChave = null; }
      this.imagemChave = await pulsarImagem(
        this, ConstantesAssets.CHAVES[chave], this._centroX(), this._centroY(),
      );
    }
  }

  async onFailure() {
    this.stopAudio(ConstantesSons.CHAVES.BG);
    await pararLoopAnimais(this);
    const chave = this.configFase?.chave;
    if (chave && ConstantesAssets.CHAVES[chave]) {
      if (this.imagemChave) { this.imagemChave.destroy(); this.imagemChave = null; }
      this.imagemChave = await silhuetaTremendo(
        this, ConstantesAssets.CHAVES[chave], this._centroX(), this._centroY(),
      );
    }
  }
}

/**
 * Cria a configuração Phaser para o jogo Quebra Cabeças.
 * Retorna o objeto de configuração usado por `new Phaser.Game(config)`
 * * @param {HTMLElement} elementoPai - Elemento DOM que conterá o canvas Phaser
 * @param {Object} configFaseAtual - Configuração da fase atual
 * @returns {Object} Configuração Phaser
 */
export const createGame = (elementoPai, configFaseAtual) => {
  const scene = new QuebraCabecasScene();

  // Caso não tenha importado ConstantesJogo, defina as dimensões e cor de fundo diretamente aqui
  return {
    type: Phaser.AUTO,
    width: ConstantesJogo.LARGURA_TELA,
    height: ConstantesJogo.ALTURA_TELA,
    backgroundColor: ConstantesJogo.COR_FUNDO,
    parent: elementoPai,
    scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH },
    scene: scene,
    callbacks: {
      preBoot: function (game) {
        game.registry.set("configFase", configFaseAtual);
        game.registry.set("gameConfig", gameConfig);
      },
    },
  };
};