import { world, DynamicPropertiesDefinition } from "@minecraft/server";
import { ActionFormData, ModalFormData } from "@minecraft/server-ui";
import { POKEMONS_DATA, POKEMON_CAN_LEARN } from "./allanz/data/pokemon.js";
import { MOVEMENTS_DATA } from "./allanz/data/movement.js";

// --- Helpers ---
const TRAINER_ID_MARKER = "_trainer";
const PROP_TEAM = "pr:trainer_team";     // stringified JSON
const PROP_ROUND = "pr:trainer_round";   // number

function isTrainerEntity(entity) {
  try {
    const id = entity?.typeId ?? "";
    return id.startsWith("pr:") && id.includes(TRAINER_ID_MARKER);
  } catch {
    return false;
  }
}

function getTrainerTypeFromId(typeId) {
  const id = (typeId ?? "").toLowerCase();
  if (id.includes("poison")) return "poison";
  if (id.includes("fire")) return "fire";
  if (id.includes("water")) return "water";
  if (id.includes("ghost")) return "ghost";
  if (id.includes("fairy")) return "fairy";
  if (id.includes("rock")) return "rock";
  if (id.includes("fighter") || id.includes("fighting")) return "fighting";
  if (id.includes("thunder") || id.includes("electric")) return "electric";
  if (id.includes("grass")) return "grass";
  if (id.includes("psychic") || id.includes("physic")) return "psychic";
  return "trainer";
}

const MOVE_NAME_BY_ID = new Map(MOVEMENTS_DATA.map(m => [m.id, m.name ?? m.id]));
const POKEMON_OPTIONS = POKEMONS_DATA.map(p => p.id);
const POKEMON_LABELS = POKEMONS_DATA.map(p => p.id.replace("pr:", ""));

// Default team structure
function makeEmptyTeam() {
  return {
    slots: [
      null, null, null, null, null, null
    ]
  };
}

function loadTeam(entity) {
  const raw = entity.getDynamicProperty(PROP_TEAM);
  if (typeof raw === "string" && raw.trim().length) {
    try { return JSON.parse(raw); } catch {}
  }
  return makeEmptyTeam();
}

function saveTeam(entity, team) {
  entity.setDynamicProperty(PROP_TEAM, JSON.stringify(team));
}

function getLearnsetMoves(pokemonId) {
  // POKEMON_CAN_LEARN is a Map keyed by base name without namespace.
  const base = (pokemonId ?? "").replace("pr:", "");
  const list = POKEMON_CAN_LEARN.get(base);
  if (Array.isArray(list) && list.length) return list;
  // fallback: allow all moves if no learnset found
  return MOVEMENTS_DATA.map(m => m.id);
}

async function showChallengeMenu(player, trainer) {
  const type = getTrainerTypeFromId(trainer.typeId);
  const round = Number(trainer.getDynamicProperty(PROP_ROUND) ?? 0);
  const nextRound = Math.min(round + 1, 6);

  const form = new ActionFormData();
  form.title("Trainer Challenge");
  form.body(`Trainer: §e${trainer.typeId}§r\nType: §b${type}§r\n\nChoose an option:`);

  // Use your provided UI textures as button icons if they exist in RP.
  form.button(`Start Round ${nextRound}`, "textures/ui/button_default");
  form.button("Cancel", "textures/ui/button_hover");

  const res = await form.show(player);
  if (res.canceled) return;

  if (res.selection === 0) {
    // Start next round
    trainer.setDynamicProperty(PROP_ROUND, nextRound);

    // Fire a script event that your battle system can hook.
    // Payload kept simple to avoid quoting issues.
    try {
      player.runCommand(`scriptevent pr:trainer_battle ${trainer.typeId} ${type} ${nextRound}`);
    } catch {}

    // Basic feedback
    player.sendMessage(`§aStarting battle vs §e${trainer.typeId}§a (type §b${type}§a) — Round ${nextRound}/6`);
  }
}

async function showEditMenu(player, trainer) {
  const team = loadTeam(trainer);

  const form = new ActionFormData();
  form.title("Edit Trainer");
  form.body(`Editing: §e${trainer.typeId}§r\n\nPick a slot to edit:`);

  for (let i = 0; i < 6; i++) {
    const slot = team.slots[i];
    const label = slot ? `${i+1}. ${slot.pokemon} (Lv ${slot.level})` : `${i+1}. (empty)`;
    form.button(label, "textures/ui/pokeicon");
  }
  form.button("Reset Trainer Rounds", "textures/ui/arrow");
  form.button("Close", "textures/ui/null");

  const res = await form.show(player);
  if (res.canceled) return;

  if (res.selection >= 0 && res.selection <= 5) {
    await editSlot(player, trainer, res.selection, team);
    return;
  }
  if (res.selection === 6) {
    trainer.setDynamicProperty(PROP_ROUND, 0);
    player.sendMessage("§aTrainer rounds reset to 0.");
    return;
  }
}

async function editSlot(player, trainer, idx, team) {
  const current = team.slots[idx] ?? null;

  // First: choose pokemon + level
  const f1 = new ModalFormData();
  f1.title(`Slot ${idx+1}`);
  f1.dropdown("Pokemon", POKEMON_LABELS, Math.max(0, POKEMON_OPTIONS.indexOf(current?.pokemon ?? "pr:bulbasaur")));
  f1.slider("Level", 1, 100, 1, Number(current?.level ?? 10));

  const r1 = await f1.show(player);
  if (r1.canceled) return;

  const pokemon = POKEMON_OPTIONS[r1.formValues[0]];
  const level = Number(r1.formValues[1]);

  // Second: choose 4 moves (from learnset)
  const learnset = getLearnsetMoves(pokemon);
  const moveLabels = learnset.map(id => `${MOVE_NAME_BY_ID.get(id) ?? id} (${id})`);

  const f2 = new ModalFormData();
  f2.title(`Moves — ${pokemon.replace("pr:", "")}`);
  const defMoves = Array.isArray(current?.moves) ? current.moves : [];
  const defIndex = (mid) => Math.max(0, learnset.indexOf(mid));

  f2.dropdown("Move 1", moveLabels, defIndex(defMoves[0]));
  f2.dropdown("Move 2", moveLabels, defIndex(defMoves[1] ?? defMoves[0]));
  f2.dropdown("Move 3", moveLabels, defIndex(defMoves[2] ?? defMoves[0]));
  f2.dropdown("Move 4", moveLabels, defIndex(defMoves[3] ?? defMoves[0]));

  const r2 = await f2.show(player);
  if (r2.canceled) return;

  const moves = [
    learnset[r2.formValues[0]],
    learnset[r2.formValues[1]],
    learnset[r2.formValues[2]],
    learnset[r2.formValues[3]],
  ];

  team.slots[idx] = { pokemon, level, moves };
  saveTeam(trainer, team);

  player.sendMessage(`§aSaved Slot ${idx+1}: §e${pokemon}§a Lv§e${level}§a`);
}


world.afterEvents.worldInitialize.subscribe(e => {
  // Register dynamic properties on trainer entities.
  const def = new DynamicPropertiesDefinition();
  def.defineString(PROP_TEAM, 12000);
  def.defineNumber(PROP_ROUND);

  const trainerTypes = [
  "pr:fairy_trainer",
  "pr:fighter_trainer",
  "pr:fire_trainer",
  "pr:fire_trainer_2",
  "pr:ghost_trainer_2",
  "pr:poison_trainer_2",
  "pr:rock_trainer_girl",
  "pr:thunder_grass_trainer_2",
  "pr:water_trainer_girl",
  "pr:water_trainer_girl_fisher"
];

  for (const typeId of trainerTypes) {
    try {
      e.propertyRegistry.registerEntityTypeDynamicProperties(def, typeId);
    } catch {}
  }
});


world.beforeEvents.playerInteractWithEntity.subscribe(async (ev) => {
  try {
    const player = ev.player;
    const target = ev.target;
    if (!isTrainerEntity(target)) return;

    // Don't let interaction do other things (reduces conflicts)
    ev.cancel = true;

    const gm = player.getGameMode?.() ?? "survival";
    if (gm === "creative") {
      await showEditMenu(player, target);
    } else {
      await showChallengeMenu(player, target);
    }
  } catch (err) {
    // silent
  }
});
