import { world, EquipmentSlot, system , GameMode} from "@minecraft/server";
import { playAnimationWithClock, AnimationHelper } from "./animation_controller";
import { isHoldingWeapon } from "./combat_mechanic";
import { ActionFormData } from '@minecraft/server-ui';

// =================== SIGN DEFINITIONS ===================
export const Signs = {
  "aard": { 
    useTime: 10, 
    effectTime: 2,
    animation: "animation.combat.sign_use", 
    sound: "aard",
    particle: "imc_pa:aard",
    handler: useAardSign
  },
  "yrden": { 
    useTime: 40, 
    effectTime: 20,
    animation: "animation.combat.sign_use_aoe", 
    sound: "yrden",
    particle: "imc_pa:yrden",
    handler: useYrdenSign
  },
  "igni": { 
    useTime: 20, 
    effectTime: 5,
    animation: "animation.combat.sign_use_aoe", 
    sound: "igni",
    particle: "imc_pa:igni",
    handler: useIgniSign
  },
  "quen": { 
    useTime: 40, 
    effectTime: 20,
    animation: "animation.combat.sign_use", 
    sound: "quen",
    particle: "imc_pa:quen",
    handler: useQuenSign
  },
  "axii": { 
    useTime: 40, 
    effectTime: 5,
    animation: "animation.combat.sign_use", 
    sound: "axii",
    particle: "imc_pa:axii",
    handler: useAxiiSign
  }
};

// =================== SIGN HANDLERS ===================
function useAardSign(player) {
  const dir = player.getViewDirection();
  const entities = player.dimension.getEntities({
  location: player.location,
    maxDistance: 5,
    families: ["mob"] // only living mobs
  });
  player.runCommand(`camerashake add @s 0.1 1 positional`);
  player.runCommand(`particle imc_pa:aard_vfx ~~1~`);
  player.sendMessage("§b[Aard]§r You unleash a telekinetic blast!");
  for (const e of entities) {
    if (e.id === player.id) continue;
    const horizontalForce = { x: dir.x * 6, z: dir.z * 6 }; // horizontal knockback strength - xz vector
    const verticalStrength = 1;
    e.applyKnockback(horizontalForce, verticalStrength);
    e.addEffect("slowness", 100, { amplifier: 1, showParticles: true });
    e.addEffect("blindness", 100, { amplifier: 1, showParticles: true });
    e.addEffect("weakness", 100, { amplifier: 1, showParticles: true });
    e.applyDamage(5, { cause: "magic" });
  }
}

function useYrdenSign(player) {
    const spawnX = player.location.x;
    const spawnY = player.location.y;
    const spawnZ = player.location.z;
    const spawnedEntity = player.dimension.spawnEntity("imc:yrden_circle", {
        x: spawnX,
        y: spawnY,
        z: spawnZ
    });
    spawnedEntity.addTag("yrden_id:" + player.id);
    player.addTag("yrden_id:" + player.id);
    player.sendMessage("§5[Yrden]§r You place a magical trap!");
}

function useIgniSign(player) {
  const entities = player.dimension.getEntities({ location: player.location, maxDistance: 5 });
  for (const e of entities) {
    if (e.id === player.id) continue;
    e.setOnFire(10, true);
    e.applyDamage(10, { cause: "fire"});
  }
  player.runCommand(`particle imc_pa:igni_vfx ~~1~`);
  player.runCommand(`particle imc_pa:igni_vfx_smoke ~~~`);
  player.runCommand(`camerashake add @s 0.15 1 positional`);
  player.sendMessage("§c[Igni]§r You cast a fiery burst!");
}

function useQuenSign(player) {
  player.addEffect("absorption", 200, { amplifier: 2, showParticles: true });
  player.addEffect("resistance", 200, { amplifier: 1, showParticles: true });
  player.sendMessage("§e[Quen]§r A protective shield surrounds you!");
  player.runCommand(`camerashake add @s 0.15 1 positional`);
}

function useAxiiSign(player) {
  const entities = player.dimension.getEntities({ location: player.location, maxDistance: 5 });
  for (const e of entities) {
    if (e.id === player.id) continue;
    e.addEffect("weakness", 100, { amplifier: 255, showParticles: true });
    e.addEffect("slowness", 100, { amplifier: 255, showParticles: true });
    e.addEffect("blindness", 200, { amplifier: 255, showParticles: true });
    e.addEffect("nausea", 200, { amplifier: 1, showParticles: true });
  }
  player.runCommand(`camerashake add @s 0.5 0.3 positional`);
  player.sendMessage("§d[Axii]§r You cloud your target's mind...");
}

// =================== STATE STORAGE ===================
export const usingSigns = new Map();

// =================== CORE USE FUNCTION ===================
export function useSign(player, signKey) {
  const now = system.currentTick;
  const sign = Signs[signKey];
  if (!sign) return;

  // Cooldown check
  const state = usingSigns.get(player.id);
  if (state && state.expiry > now) {
    const ticksLeft = state.expiry - now;
    player.sendMessage(`§c[Cooldown]§r You must wait ${ticksLeft} ticks before using ${signKey} again!`);
    return;
  }

  const expiry = now + sign.useTime;
  usingSigns.set(player.id, { startTick: now, expiry });
  clearItem(player)

  // Casting animation + sound
  if (sign.animation) {
    playAnimationWithClock(player, AnimationHelper(sign.animation, player), sign.useTime)
    player.runCommand(`/particle ${sign.particle} ~~~`);
  }
  if (sign.sound) {
    player.runCommand(`playsound ${sign.sound} @s`);
  }

  // Apply "casting lock"
  player.addEffect("slowness", sign.useTime, { amplifier: 1, showParticles: false });

  // Cleanup when expired
  system.runTimeout(() => {
    const state = usingSigns.get(player.id);
    if (state && state.expiry === expiry) {
      usingSigns.delete(player.id);
    }
  }, sign.useTime);

  // Trigger the effect AFTER cast delay
  system.runTimeout(() => {
    const state = usingSigns.get(player.id);
    if (state && state.expiry === expiry && typeof sign.handler === "function") {
      sign.handler(player);
    }
  }, sign.effectTime);
}

// =================== EVENT HOOK ===================
world.afterEvents.itemUse.subscribe((eventData) => {
  const { source: player } = eventData;
  if (!player || player.typeId !== "minecraft:player") return;
  if (!player.getDynamicProperty("combat_state")) return;
  if (!isHoldingWeapon(player)) return;

  const equippable = player.getComponent("minecraft:equippable");
  if (!equippable) return;
  const hasSignItem = checkInventoryHaveSign(player);
  if (player.isSneaking && hasSignItem) {
    SignSelect(player);
  }

  const hasItem = checkInventory(player);

  if (!player.isSneaking) {
    if (hasItem){
      useSign(player, player.getDynamicProperty("sign")); // trigger effect
    }
    else {
      player.sendMessage("You Have No Available Sign to Cast")
    }
  }
});


const signKeywords = [
  "aard",
  "yrden",
  "quen",
  "igni",
  "axii"
];

export function checkInventoryHaveSign(player) {
  try {
    const inventory = player.getComponent("minecraft:inventory");
    if (!inventory) return false;

    const container = inventory.container;
    if (!container) return false;

    for (let i = 0; i < container.size; i++) {
      const item = container.getItem(i);
      if (!item) continue;

      const id = item.typeId.toLowerCase();

      // Check if any keyword matches the item type ID
      if (signKeywords.some(keyword => id.includes(keyword))) {
        return true;
      }
    }

    return false;
  } catch (err) {
    console.warn(`[checkInventory] Error checking ${player.name}: ${err}`);
    return false;
  }
}


function checkInventory(player) {
    const inventory = player.getComponent("minecraft:inventory")?.container;
    if (!inventory) return false;

    const sign = player.getDynamicProperty("sign");
    if (!sign) return false;

    for (let i = 0; i < inventory.size; i++) {
        const item = inventory.getItem(i);
        if (item && item.typeId.includes(sign)) {
            return true;
        }
    }
    return false;
}

function clearItem(source) {
    if (!source) return;

    const inventory = source.getComponent("minecraft:inventory")?.container;
    if (!inventory) return;

    const sign = source.getDynamicProperty("sign");
    if (!sign) return;

    if (source.getGameMode() === GameMode.Creative) return;

    for (let i = 0; i < inventory.size; i++) {
        const item = inventory.getItem(i);
        if (!item) continue;

        // Check if this item id contains the sign word
        if (item.typeId.includes(sign)) {
            if (item.amount > 1) {
                item.amount--;                 // decrease stack size
                inventory.setItem(i, item);    // update slot
            } else {
                inventory.setItem(i, undefined); // remove stack entirely
            }
            return; // stop after clearing 1 item
        }
    }
}



system.afterEvents.scriptEventReceive.subscribe((event) => {
  const entity = event.sourceEntity;
  if (!entity || entity.typeId !== "imc:yrden_circle") return;

  if (event.id === "imc:yrden") {
    let tags = entity.getTags();
    entity.runCommand(
        `effect @e[r=5, tag=!${tags}] slowness 1 3`
    );
    entity.runCommand(
        `effect @e[r=5, tag=!${tags}] weakness 1 1`
    );

    const entities = entity.dimension.getEntities({ location: entity.location, maxDistance: 5 });
    for (const e of entities) {
    const familyComp = e.getComponent("minecraft:type_family");
    if (familyComp && familyComp.hasTypeFamily("undead")) {
        e.applyDamage(3, { cause: "magic" });
    }
    }

  }
  if (event.id === "imc:yrden_stop") {
    const circleTags = entity.getTags();
    const allEntities = entity.dimension.getEntities({
        location: entity.location,
        maxDistance: 64
    });

    // Look for another Yrden circle (not this one) with overlapping tags
    const hasNearbySameTag = allEntities.some(e => {
        if (e.id === entity.id) return false; // skip self
        if (e.typeId !== "imc:yrden_circle") return false;

        const otherTags = e.getTags();
        // check if any tag overlaps
        return circleTags.some(tag => otherTags.includes(tag));
    });

    // Only remove if no other circle with same tag is nearby
    if (!hasNearbySameTag) {
        for (const tag of circleTags) {
            entity.runCommand(`tag @a[tag=${tag}] remove ${tag}`);
        }
    }
}
});



function SignSelect(player) {
    const sign = player.getDynamicProperty("sign") ?? "None";

    const form = new ActionFormData()
        .title(`§l§2⚒ Signs Selection`)
        .body(
`§2§l➤ §r§fSigns: ${sign}`
        )
        .button("§b AARD")
        .button("§5 YRDEN")
        .button("§c IGNI")
        .button("§e QUEN")
        .button("§d AXII");

    form.show(player).then(r => {
        if (r.canceled) {
            exit(player);
            return;
        }

        if (r.selection === 0) {
          player.setDynamicProperty("sign", "aard")
          button(player)
        }

        if (r.selection === 1) {
          player.setDynamicProperty("sign", "yrden")
          button(player)
        }

        if (r.selection === 2) {
          player.setDynamicProperty("sign", "igni")
          button(player)
        }

        if (r.selection === 3) {
          player.setDynamicProperty("sign", "quen")
          button(player)
        }
        if (r.selection === 4) {
          player.setDynamicProperty("sign", "axii");
          button(player)
        }
    });
    popup(player);
}


function popup(player){
    player.playSound("sign_popup")
}

function exit(player){
    player.runCommand("/stopsound @s random.click")
    player.playSound("sign_popup")
}

function button(player){
    player.runCommand("/stopsound @s random.click")
    player.playSound("sign_select")
}
