/**
 * @fileoverview Utility module for blocks.js
 * 
 * @module games.mole-mash.blocks.blocks
 */

import * as Blockly from "blockly/core";
import "blockly/blocks";
import { javascriptGenerator } from "blockly/javascript";

const HUE_CONDICIONAIS = "#5B80A5";
const HUE_MOVIMENTO = "#8B4513";
const HUE_LOGICA = "#59C059";
const HUE_MATEMATICA = "#8BC34A";
const HUE_VARIAVEIS = "#9C27B0";
const HUE_REPETICAO = "#FF9800";
const HUE_TEMPO = "#FF5722";

/**
 * Registra todos os blocos personalizados do MoleMash no Blockly.
 * Executa definição de blocos e geradores.
 * @returns {void}
 */
export const registerBlocks = () => {
  defineBlocks();
  defineGenerators();
};

const defineBlocks = () => {
  Blockly.Blocks["mover_toupeira"] = {
    init: function () {
      this.jsonInit({
        message0: "mover para Linha %1 Coluna %2",
        args0: [
          { type: "input_value", name: "LINHA", check: "Number" },
          { type: "input_value", name: "COLUNA", check: "Number" },
        ],
        inputsInline: true,
        previousStatement: null,
        nextStatement: null,
        colour: HUE_MOVIMENTO,
        tooltip:
          "Move a toupeira para uma posição específica (1 a 3) na matriz.",
      });
    },
  };

  Blockly.Blocks["aguardar"] = {
    init: function () {
      this.jsonInit({
        message0: "aguardar %1 segundos",
        args0: [
          {
            type: "field_number",
            name: "TEMPO",
            value: 1,
            min: 0,
            max: 10,
          },
        ],
        previousStatement: null,
        nextStatement: null,
        colour: HUE_TEMPO,
        tooltip: "Pausa a execução antes do próximo movimento.",
      });
    },
  };

  Blockly.Blocks["repetir_sempre"] = {
    init: function () {
      this.appendDummyInput().appendField("repetir para sempre");
      this.appendStatementInput("STACK").setCheck(null).appendField("faça");
      this.setPreviousStatement(true, null);
      this.setColour(HUE_REPETICAO);
      this.setTooltip("Executa os blocos dentro dele em um ciclo infinito.");
    },
  };
};

/**
 * Define os geradores JavaScript associados aos blocos do MoleMash.
 * @private
 * @returns {void}
 */
const defineGenerators = () => {
  javascriptGenerator.STATEMENT_PREFIX = "highlightBlock(%1);\n";
  javascriptGenerator.addReservedWords("highlightBlock");

  javascriptGenerator.forBlock["mover_toupeira"] = (block) => {
    const linha =
      javascriptGenerator.valueToCode(
        block,
        "LINHA",
        javascriptGenerator.ORDER_ATOMIC,
      ) || "1";
    const coluna =
      javascriptGenerator.valueToCode(
        block,
        "COLUNA",
        javascriptGenerator.ORDER_ATOMIC,
      ) || "1";
    return `moverToupeira(${linha}, ${coluna});\n`;
  };

  javascriptGenerator.forBlock["aguardar"] = (block) => {
    const tempo = block.getFieldValue("TEMPO");
    return `aguardar(${tempo * 1000});\n`;
  };

  javascriptGenerator.forBlock["repetir_sempre"] = (block) => {
    const branch = javascriptGenerator.statementToCode(block, "STACK");
    return `while (true) {\n${branch}  await esperar(10); // Segurança para não travar\n}\n`;
  };
};

/**
 * Gera uma toolbox dinâmica filtrada pelos blocos permitidos para a fase.
 * @param {string[]} [allowedBlocks=[]] - Lista de tipos de blocos permitidos.
 * @returns {Object} Estrutura JSON compatível com a toolbox do Blockly.
 */
export const generateDynamicToolbox = (allowedBlocks = []) => {
  const blockDefinitions = {
    // Movimento
    mover_toupeira: {
      kind: "block",
      type: "mover_toupeira",
    },
    // Repetição
    repetir_sempre: {
      kind: "block",
      type: "repetir_sempre",
    },
    controls_repeat_ext: {
      kind: "block",
      type: "controls_repeat_ext",
    },
    controls_whileUntil: {
      kind: "block",
      type: "controls_whileUntil",
    },
    // Tempo
    aguardar: {
      kind: "block",
      type: "aguardar",
    },
    // Lógica
    logic_compare: {
      kind: "block",
      type: "logic_compare",
    },
    logic_operation: {
      kind: "block",
      type: "logic_operation",
    },
    logic_negate: {
      kind: "block",
      type: "logic_negate",
    },
    logic_boolean: {
      kind: "block",
      type: "logic_boolean",
    },
    controls_if: {
      kind: "block",
      type: "controls_if",
    },
    controls_ifelse: {
      kind: "block",
      type: "controls_ifelse",
    },
    // Matemática
    math_number: {
      kind: "block",
      type: "math_number",
    },
    math_arithmetic: {
      kind: "block",
      type: "math_arithmetic",
    },
    math_random_int: {
      kind: "block",
      type: "math_random_int",
      inputs: {
        FROM: { shadow: { type: "math_number", fields: { NUM: 1 } } },
        TO: { shadow: { type: "math_number", fields: { NUM: 3 } } },
      },
    },
  };

  const toolboxContents = {
    kind: "categoryToolbox",
    contents: [
      {
        kind: "category",
        name: "Movimento",
        colour: HUE_MOVIMENTO,
        contents: [],
        cssConfig: { container: "movimento" },
      },
      {
        kind: "category",
        name: "Repetição",
        colour: HUE_REPETICAO,
        contents: [],
        cssConfig: { container: "repeticao" },
      },
      {
        kind: "category",
        name: "Lógica",
        colour: HUE_LOGICA,
        contents: [],
        cssConfig: { container: "logica" },
      },
      {
        kind: "category",
        name: "Condicionais",
        colour: HUE_CONDICIONAIS,
        contents: [],
        cssConfig: { container: "condicionais" },
      },
      {
        kind: "category",
        name: "Matemática",
        colour: HUE_MATEMATICA,
        contents: [],
        cssConfig: { container: "matematica" },
      },
      {
        kind: "category",
        name: "Tempo",
        colour: HUE_TEMPO,
        contents: [],
        cssConfig: { container: "tempo" },
      },
      {
        kind: "category",
        name: "Variáveis",
        colour: HUE_VARIAVEIS,
        custom: "VARIABLE",
        cssConfig: { container: "variaveis" },
      },
    ],
  };

  allowedBlocks.forEach((blockId) => {
    const blockDef = blockDefinitions[blockId];

    if (blockId === "mover_toupeira") {
      toolboxContents.contents[0].contents.push(blockDef);
    } else if (
      ["repetir_sempre", "controls_repeat_ext", "controls_whileUntil"].includes(
        blockId,
      )
    ) {
      toolboxContents.contents[1].contents.push(blockDef);
    } else if (
      [
        "logic_compare",
        "logic_operation",
        "logic_negate",
        "logic_boolean",
      ].includes(blockId)
    ) {
      toolboxContents.contents[2].contents.push(blockDef);
    } else if (["controls_if", "controls_ifelse"].includes(blockId)) {
      toolboxContents.contents[3].contents.push(blockDef);
    } else if (
      ["math_number", "math_random_int", "math_arithmetic"].includes(blockId)
    ) {
      toolboxContents.contents[4].contents.push(blockDef);
    } else if (blockId === "aguardar") {
      toolboxContents.contents[5].contents.push(blockDef);
    }
  });

  const hasVariables =
    allowedBlocks.includes("variables_set") ||
    allowedBlocks.includes("variables_get") ||
    allowedBlocks.includes("variables");

  toolboxContents.contents = toolboxContents.contents.filter(
    (category, index) => {
      if (category.custom === "VARIABLE") {
        return hasVariables;
      }
      return category.contents && category.contents.length > 0;
    },
  );

  return toolboxContents;
};
