import { world } from "@minecraft/server";

// Uses scoreboard commands so we don't rely on Dynamic Properties registration.
const OBJ = "pr_learn_points";

function overworld() {
  try { return world.getDimension("overworld"); } catch (e) { return null; }
}

async function run(cmd) {
  const dim = overworld();
  if (!dim) return;
  try {
    if (dim.runCommandAsync) return await dim.runCommandAsync(cmd);
  } catch (e) { }
  try { return dim.runCommand(cmd); } catch (e) { }
}

async function ensureObjective() {
  await run(`scoreboard objectives add ${OBJ} dummy`);
}

function key(player, slotNum) {
  const name = String(player?.nameTag ?? player?.name ?? "player").replace(/[^a-zA-Z0-9_]/g, "_");
  return `lp_${name}_s${slotNum}`;
}

export async function cacheLearnPoints(player, slotNum, value) {
  try {
    const s = Math.max(1, Math.min(6, Number(slotNum) || 1));
    player.setDynamicProperty(`pr:lp_cache_${s}`, Math.max(0, Math.floor(Number(value) || 0)));
  } catch (e) { }
}

export async function getLearnPoints(player, slotNum) {
  if (!player) return 0;
  const s = Math.max(1, Math.min(6, Number(slotNum) || 1));
  const k = key(player, s);

  // Preferred: try API first if available
  try {
    const obj = world.scoreboard?.getObjective?.(OBJ);
    if (obj) {
      const part = obj.getParticipants().find(p => p.displayName === k);
      if (!part) return 0;
      const v = obj.getScore(part);
      return Number.isFinite(v) ? v : 0;
    }
  } catch (e) { }

  // Fallback: cached DP
  try {
    const raw = player.getDynamicProperty(`pr:lp_cache_${s}`);
    const n = Number(raw);
    return Number.isFinite(n) ? n : 0;
  } catch (e) {
    return 0;
  }
}

export async function addLearnPoints(player, slotNum, delta = 1) {
  if (!player) return 0;
  const s = Math.max(1, Math.min(6, Number(slotNum) || 1));
  const d = Math.floor(Number(delta) || 0);
  if (!d) return await getLearnPoints(player, s);

  let cached = 0;
  try { cached = Number(player.getDynamicProperty(`pr:lp_cache_${s}`)) || 0; } catch (e) { }

  await ensureObjective();
  const k = key(player, s);
  await run(`scoreboard players add "${k}" ${OBJ} ${d}`);

  const total = await getLearnPoints(player, s);
  const finalTotal = (total || (cached + d));
  await cacheLearnPoints(player, s, finalTotal);
  return finalTotal;
}

export async function spendLearnPoint(player, slotNum) {
  const cur = await getLearnPoints(player, slotNum);
  if (cur <= 0) return false;
  await ensureObjective();
  const s = Math.max(1, Math.min(6, Number(slotNum) || 1));
  const k = key(player, s);
  await run(`scoreboard players remove "${k}" ${OBJ} 1`);
  await cacheLearnPoints(player, s, Math.max(0, cur - 1));
  return true;
}


export function getLearnPointsSync(player, slotNum) {
  if (!player) return 0;
  const s = Math.max(1, Math.min(6, Number(slotNum) || 1));
  const k = key(player, s);

  // Prefer scoreboard API if objective exists
  try {
    const obj = world.scoreboard?.getObjective?.(OBJ);
    if (obj) {
      const part = obj.getParticipants().find(p => p.displayName === k);
      if (!part) return 0;
      const v = obj.getScore(part);
      return Number.isFinite(v) ? v : 0;
    }
  } catch (e) { }

  // Fallback: cached DP (may be unavailable if not registered)
  try {
    const raw = player.getDynamicProperty(`pr:lp_cache_${s}`);
    const n = Number(raw);
    return Number.isFinite(n) ? n : 0;
  } catch (e) {
    return 0;
  }
}
