import { world, system, ItemStack } from "@minecraft/server";

// ─── Constants ──────────────────────────────────────────────
const HOME_BLOCK = "silverlabs:home_sign";
const PROP_KEY = "home_signs_v1";

const HOME_RADIUS = 32;            // user-facing "home area" size
const STRAY_RADIUS = 16;           // cat is nudged back beyond this — keeps cats actually at home, not just "within shouting distance"
const RETURN_RADIUS_MIN = 2;
const RETURN_RADIUS_MAX = 10;
const TICK_INTERVAL = 40;          // 2 s

// ─── State ──────────────────────────────────────────────────
// In-memory mirror: { "x,y,z,dim": { ownerId, ownerName } }
let homes = {};

function loadState() {
  try {
    const raw = world.getDynamicProperty(PROP_KEY);
    if (raw && typeof raw === "string") {
      homes = JSON.parse(raw);
    }
  } catch (e) {
    world.sendMessage(`§c[Home Sweet Home] Failed to load state: ${e.message}`);
    homes = {};
  }
}

function saveState() {
  try {
    world.setDynamicProperty(PROP_KEY, JSON.stringify(homes));
  } catch (e) {
    world.sendMessage(`§c[Home Sweet Home] Failed to save state: ${e.message}`);
  }
}

function keyOf(loc, dimensionId) {
  return `${Math.floor(loc.x)},${Math.floor(loc.y)},${Math.floor(loc.z)},${dimensionId}`;
}

function claim(loc, dimensionId, player) {
  homes[keyOf(loc, dimensionId)] = { ownerId: player.id, ownerName: player.name };
  saveState();
}

function release(loc, dimensionId) {
  delete homes[keyOf(loc, dimensionId)];
  saveState();
}

function getOwner(loc, dimensionId) {
  return homes[keyOf(loc, dimensionId)] || null;
}

// ─── Placement: claim home zone ────────────────────────────
world.afterEvents.playerPlaceBlock.subscribe((event) => {
  const block = event.block;
  if (block.typeId !== HOME_BLOCK) return;
  const player = event.player;
  claim(block.location, block.dimension.id, player);
  player.sendMessage(
    `§a[Home Sweet Home] §7Home zone set — tamed cats will stay within ${HOME_RADIUS} blocks.`
  );
});

// ─── Break: owner-only ─────────────────────────────────────
try {
  world.beforeEvents.playerBreakBlock.subscribe((event) => {
    const block = event.block;
    if (block.typeId !== HOME_BLOCK) return;
    const owner = getOwner(block.location, block.dimension.id);
    if (!owner) return; // unclaimed — let it break

    const player = event.player;
    if (owner.ownerId !== player.id) {
      event.cancel = true;
      system.run(() =>
        player.sendMessage(
          `§c[Home Sweet Home] §7This sign belongs to §f${owner.ownerName}§7. You can't break it.`
        )
      );
      return;
    }

    // Owner break — drop the item back, clear the registry, remove the block.
    event.cancel = true;
    const loc = { x: block.location.x, y: block.location.y, z: block.location.z };
    const dim = block.dimension;
    system.run(() => {
      try {
        const dropPos = { x: loc.x + 0.5, y: loc.y + 0.5, z: loc.z + 0.5 };
        dim.spawnItem(new ItemStack(HOME_BLOCK, 1), dropPos);
        dim.runCommand(`setblock ${loc.x} ${loc.y} ${loc.z} air`);
      } catch (e) {
        player.sendMessage(`§c[Home Sweet Home] Error during break: ${e.message}`);
      }
      release(loc, dim.id);
    });
  });
} catch (e) {
  console.warn(`[Home Sweet Home] beforeEvents.playerBreakBlock unavailable: ${e}`);
}

// ─── Cat homing: nudge stray tamed cats back to the nearest home ──
function homesByDimension() {
  const out = {};
  for (const key in homes) {
    const [xs, ys, zs, dim] = key.split(",");
    if (!out[dim]) out[dim] = [];
    out[dim].push({
      x: parseInt(xs, 10) + 0.5,
      y: parseInt(ys, 10) + 0.5,
      z: parseInt(zs, 10) + 0.5,
      ownerName: homes[key].ownerName,
    });
  }
  return out;
}

function nearestHome(catLoc, homeList) {
  let best = null;
  let bestD2 = Infinity;
  for (const h of homeList) {
    const dx = catLoc.x - h.x;
    const dy = catLoc.y - h.y;
    const dz = catLoc.z - h.z;
    const d2 = dx * dx + dy * dy + dz * dz;
    if (d2 < bestD2) {
      bestD2 = d2;
      best = h;
    }
  }
  return { home: best, distance: Math.sqrt(bestD2) };
}

function pickReturnSpot(home) {
  const angle = Math.random() * Math.PI * 2;
  const r = RETURN_RADIUS_MIN + Math.random() * (RETURN_RADIUS_MAX - RETURN_RADIUS_MIN);
  return {
    x: home.x + Math.cos(angle) * r,
    y: home.y,
    z: home.z + Math.sin(angle) * r,
  };
}

system.runInterval(() => {
  const byDim = homesByDimension();
  const dimIds = Object.keys(byDim);
  if (dimIds.length === 0) return;

  for (const dimId of dimIds) {
    let dim;
    try {
      dim = world.getDimension(dimId);
    } catch (e) {
      continue;
    }

    let cats;
    try {
      // Tamed cats only — vanilla cats gain the "tamed" family on tame.
      cats = dim.getEntities({ type: "minecraft:cat", families: ["tamed"] });
    } catch (e) {
      continue;
    }

    for (const cat of cats) {
      try {
        const { home, distance } = nearestHome(cat.location, byDim[dimId]);
        if (!home || distance <= STRAY_RADIUS) continue;
        const target = pickReturnSpot(home);
        const ok = cat.tryTeleport(target, { checkForBlocks: true });
        if (!ok) {
          // Retry tighter
          cat.tryTeleport(
            { x: home.x, y: home.y, z: home.z },
            { checkForBlocks: false }
          );
        }
      } catch (e) {
        // Skip bad cat, continue with next
      }
    }
  }
}, TICK_INTERVAL);

// ─── Boot ──────────────────────────────────────────────────
system.run(() => {
  loadState();
  world.sendMessage("§a[Home Sweet Home] §7Loaded — place a sign to claim a 32-block home zone.");
});
