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

const FLIGHT_TAG = "pb_gat_flight_active";
const JUMP_RESET_TIME = 20;
const REQUIRED_JUMPS = 2;

const nearGroundTimers = new Map();
const NEAR_GROUND_THRESHOLD = 0.5; // distance from ground in blocks
const NEAR_GROUND_DURATION = 20; // ticks to wait (1 second)

const allowedTrinketTags = [
  "pb_gat_trinket_infinity_cube_1",
  "pb_gat_trinket_infinity_cube_2",
  "pb_gat_trinket_infinity_cube_3",
  "pb_gat_trinket_pocket_universe_1",
  "pb_gat_trinket_pocket_universe_2",
  "pb_gat_trinket_pocket_universe_3",
];

const flightMessageTimers = new Map();
const jumpTracker = new Map();
const activeFlightAnimation = new Set();

function ensurePlayerState(playerId) {
  if (!jumpTracker.has(playerId)) {
    jumpTracker.set(playerId, {
      jumps: 0,
      lastJump: false,
      flightActive: false,
    });
  }
  if (!flightMessageTimers.has(playerId)) {
    flightMessageTimers.set(playerId, 0);
  }
}

export function handleFlight(player) {
  const playerId = player.id;
  ensurePlayerState(playerId);

  const jumpData = jumpTracker.get(playerId);
  const messageTimer = flightMessageTimers.get(playerId);

  const isOnGround = player.isOnGround;
  const hasFlightTag = player.hasTag(FLIGHT_TAG);
  let isRiding = null;
  try {
    const ridingComp = player.getComponent("minecraft:riding");
    isRiding = ridingComp ? ridingComp.entityRidingOn : null;
  } catch (e) {
    isRiding = null; // fallback safe value
  }

  // === Sneak dismount override ===
  if (hasFlightTag && !isRiding) {
    player.addEffect("slow_falling", 20, { showParticles: false });

    system.runTimeout(() => {
      const dummy = player.dimension
        .getEntities({ type: "pb_gat:flight_dummy" })
        .find((e) => e.getTags().includes(`flight_dummy_${playerId}`));

      if (dummy) {
        dummy.teleport(player.location);
        dummy.getComponent("rideable")?.addRider(player);
      }
    });
  }

  // === Stop flight when landing ===
  if (hasFlightTag && checkPlayerNearGround(player)) {
    stopFlight(player);
    jumpData.flightActive = false;
    flightMessageTimers.set(playerId, 40);
  }

  // === Double jump detection ===
  if (player.isJumping && !jumpData.lastJump) {
    jumpData.jumps++;
    jumpData.lastJump = true;

    system.runTimeout(() => (jumpData.jumps = 0), JUMP_RESET_TIME);

    if (jumpData.jumps >= REQUIRED_JUMPS) {
      if (!hasFlightTag) {
        startFlight(player);
        jumpData.flightActive = true;
        flightMessageTimers.set(playerId, 0);
      } else {
        stopFlight(player);
        jumpData.flightActive = false;
        flightMessageTimers.set(playerId, 40);
      }
      jumpData.jumps = 0;
    }
  }

  if (!player.isJumping) jumpData.lastJump = false;

  // === Message display ===
  if (messageTimer > 0) {
    // Show flight mode message while timer is running
    player.onScreenDisplay.setActionBar(
      jumpTracker.get(playerId).flightActive
        ? "Flight mode: §aActive§r"
        : "Flight mode: §cDe-activated§r"
    );
    flightMessageTimers.set(playerId, messageTimer - 1);
  }
}

function startFlight(player) {
  const playerId = player.id;
  activeFlightAnimation.delete(playerId);

  system.runTimeout(() => {
    player.addTag(FLIGHT_TAG);
    const spawnLocation = {
      x: player.location.x,
      y: player.location.y + 0.5, // 1.5 blocks higher
      z: player.location.z,
      dimension: player.dimension,
    };

    const dummy = player.dimension.spawnEntity(
      "pb_gat:flight_dummy",
      spawnLocation
    );

    dummy.addTag(`flight_dummy_${playerId}`);
    dummy.setRotation(player.getRotation());
    dummy.getComponent("rideable")?.addRider(player);
  });
}

function stopFlight(player) {
  const playerId = player.id;
  player.removeTag(FLIGHT_TAG);
  activeFlightAnimation.delete(playerId);

  const dummies = player.dimension.getEntities({ type: "pb_gat:flight_dummy" });
  for (const entity of dummies) {
    if (entity.getTags().includes(`flight_dummy_${playerId}`)) {
      entity.remove();
    }
  }
}

export function flightChecker(player) {
  const playerId = player.id;
  const hasFlightTrinket = allowedTrinketTags.some((tag) => player.hasTag(tag));
  const hasFlightTag = player.hasTag(FLIGHT_TAG);

  if (!hasFlightTrinket && hasFlightTag) {
    stopFlight(player);
    flightMessageTimers.set(playerId, 40);

    const jumpData = jumpTracker.get(playerId);
    if (jumpData) {
      jumpData.flightActive = false;
      jumpData.jumps = 0;
    }
  }

  try {
    const ride = player.getComponent("minecraft:riding")?.entityRidingOn;
    if (ride?.typeId === "pb_gat:flight_dummy") {
      if (!activeFlightAnimation.has(playerId)) {
        activeFlightAnimation.add(playerId);
        player.playAnimation("animation.pb_gat.player.flight", {
          blendOutTime: 0,
          stopExpression: "!query.is_riding",
        });
      }
    } else {
      activeFlightAnimation.delete(playerId);
    }
  } catch {
    activeFlightAnimation.delete(playerId);
  }
}

function checkPlayerNearGround(player) {
  const playerId = player.id;
  const playerPos = player.location;
  const blockBelowY = Math.floor(playerPos.y) - 1;

  // Get block at feet minus 1 (block beneath player feet)
  const blockBelow = player.dimension.getBlock({
    x: playerPos.x,
    y: blockBelowY,
    z: playerPos.z,
  });

  if (!blockBelow || blockBelow.typeId === "minecraft:air") {
    // No block found below, reset timer
    nearGroundTimers.delete(playerId);
    return false;
  }

  const distanceToGround = playerPos.y - (blockBelowY + 1);
  if (distanceToGround <= NEAR_GROUND_THRESHOLD) {
    // Player is close to ground
    let timer = nearGroundTimers.get(playerId) || 0;
    timer++;
    nearGroundTimers.set(playerId, timer);

    if (timer >= NEAR_GROUND_DURATION) {
      // Player has been near ground for long enough
      nearGroundTimers.delete(playerId);
      return true;
    }
  } else {
    // Player is not near ground, reset timer
    nearGroundTimers.delete(playerId);
  }

  return false;
}
