{
  name: "Minazuki",
  rating: 5,
  flags: {},
  minazukiFields(pokemon) {
    return [
      pokemon?.species?.id,
      pokemon?.species?.name,
      pokemon?.species?.baseSpecies,
      pokemon?.baseSpecies?.baseSpecies,
      pokemon?.baseSpecies?.name,
      pokemon?.ability,
      pokemon?.baseAbility,
      pokemon?.abilityState?.id,
      pokemon?.set?.ability,
      pokemon?.getAbility?.()?.id,
      pokemon?.name,
      pokemon?.set?.species,
      pokemon?.set?.name,
      pokemon?.speciesState?.id,
      pokemon?.details
    ].map(value => String(value || "").toLowerCase().replace(/[^a-z0-9]/g, ""));
  },
  isUnohana(pokemon) {
    const fields = this.effect.minazukiFields.call(this, pokemon);
    return fields.some(value => value === "minazuki" || value === "unohana" || value === "unohanamega" || value === "unohanabankai" || value.includes("unohana"));
  },
  isUnohanaBankai(pokemon) {
    if (pokemon?.bleachCaptainAwakened) return true;
    const fields = this.effect.minazukiFields.call(this, pokemon);
    return fields.some(value => value === "unohanamega" || value === "unohanabankai" || value.includes("unohanamega") || value.includes("unohanabankai") || value.endsWith("mega") || value.endsWith("bankai"));
  },
  ensureAura(pokemon, bankai) {
    if (!pokemon?.side) return;
    pokemon.side.addSideCondition("minazukiaura", pokemon);
    const state = pokemon.side.sideConditions["minazukiaura"];
    if (state) {
      state.unohanaSource = pokemon;
      if (bankai) state.bankai = true;
      else if (state.bankai !== true) state.bankai = false;
    }
  },
  healInactive(ally, amount) {
    ally.hp = Math.min(ally.maxhp, ally.hp + amount);
    this.add("-heal", ally, ally.getHealth, "[from] ability: Minazuki");
  },
  healLowHpAlly(ally, source, bankai) {
    if (!ally || ally.fainted || !ally.hp || !ally.maxhp || ally.hp > ally.maxhp / 2) return false;
    const abilityEffect = this.dex.abilities.get("minazuki");
    if (bankai) {
      if (ally.unohanaSitrusUsed) return false;
      ally.unohanaSitrusUsed = true;
      const amount = Math.max(1, Math.floor(ally.maxhp / 4));
      if (ally.isActive) this.heal(amount, ally, source, abilityEffect);
      else this.effect.healInactive.call(this, ally, amount);
    } else {
      if (ally.unohanaOranUsed) return false;
      ally.unohanaOranUsed = true;
      if (ally.isActive) this.heal(10, ally, source, abilityEffect);
      else this.effect.healInactive.call(this, ally, 10);
    }
    return true;
  },
  markBankaiEmergencyExit(pokemon, damage) {
    if (!pokemon || typeof damage !== "number") return false;
    if (!pokemon.hp || !pokemon.maxhp || pokemon.fainted) return false;
    if (!this.effect.isUnohanaBankai.call(this, pokemon)) return false;
    if (pokemon.hp > pokemon.maxhp * 0.30 && pokemon.hp - damage <= pokemon.maxhp * 0.30) {
      pokemon.m.unohanaEmergencyExitPending = true;
      return true;
    }
    return false;
  },
  triggerBankaiEmergencyExit(pokemon) {
    if (!pokemon?.side || pokemon.fainted || !pokemon.hp) return false;
    if (!this.canSwitch(pokemon.side)) return false;
    if (pokemon.forceSwitchFlag || pokemon.switchFlag) return false;
    pokemon.switchFlag = true;
    this.add("-activate", pokemon, "ability: Minazuki");
    return true;
  },
  applyTeamBerry(pokemon, bankai) {
    if (!pokemon?.side?.pokemon) return;
    this.effect.ensureAura.call(this, pokemon, bankai);
    for (const ally of pokemon.side.pokemon) this.effect.healLowHpAlly.call(this, ally, pokemon, bankai);
  },
  applyMinazukiField(pokemon) {
    if (!pokemon?.side?.pokemon) return;
    const abilityEffect = this.dex.abilities.get("minazuki");
    for (const ally of pokemon.side.pokemon) {
      if (!ally || ally.fainted || !ally.hp || !ally.maxhp) continue;
      const amount = Math.max(1, Math.floor(ally.maxhp / 8));
      if (ally.isActive) this.heal(amount, ally, pokemon, abilityEffect);
      else this.effect.healInactive.call(this, ally, amount);
      if (ally.status === "psn" || ally.status === "tox" || ally.status === "brn" || ally.status === "par") ally.cureStatus();
    }
  },
  restoreAlly(pokemon) {
    if (!pokemon?.side?.pokemon) return;
    const abilityEffect = this.dex.abilities.get("minazuki");
    let target = null;
    for (const ally of pokemon.side.pokemon) {
      if (!ally || ally === pokemon) continue;
      if (ally.fainted || ally.hp <= 0) {
        target = ally;
        break;
      }
    }
    if (target) {
      const wasFainted = !!target.fainted || target.hp <= 0;
      const maxhp = target.maxhp || target.baseMaxhp || 1;
      target.fainted = false;
      target.faintQueued = false;
      target.switchFlag = false;
      target.status = "";
      target.statusState = {id: "", target};
      target.hp = maxhp;
      if (wasFainted && target.side) {
        const alive = target.side.pokemon.filter(ally => ally && !ally.fainted).length;
        if (target.side.pokemonLeft < alive) target.side.pokemonLeft = alive;
        else if (target.side.pokemonLeft < target.side.pokemon.length) target.side.pokemonLeft++;
      }
      this.add("-activate", pokemon, "ability: Minazuki");
      this.add("-heal", target, target.getHealth, "[from] ability: Minazuki");
      return;
    }
    let hurt = null;
    let missing = 0;
    for (const ally of pokemon.side.pokemon) {
      if (!ally || ally === pokemon || ally.fainted || !ally.hp || !ally.maxhp) continue;
      const loss = ally.maxhp - ally.hp;
      if (loss > missing) {
        hurt = ally;
        missing = loss;
      }
    }
    if (!hurt || missing <= 0) return;
    const amount = Math.max(1, Math.floor(hurt.maxhp / 2));
    this.add("-activate", pokemon, "ability: Minazuki");
    if (hurt.isActive) this.heal(amount, hurt, pokemon, abilityEffect);
    else this.effect.healInactive.call(this, hurt, amount);
  },
  awaken(pokemon) {
    pokemon.bleachCaptainAwakened = true;
    const abilityEffect = this.dex.abilities.get("minazuki");
    this.add("-activate", pokemon, "ability: Minazuki");
    if (!pokemon.formeChange("Unohana-Bankai", abilityEffect, true)) {
      pokemon.bleachCaptainAwakened = false;
      return;
    }
    pokemon.canMegaEvo = null;
    const hpBaseStat = pokemon.species.baseStats?.hp ?? pokemon.species.baseStats?.["hp"] ?? 1;
    const hpIV = pokemon.set?.ivs?.hp ?? 31;
    const hpEV = pokemon.set?.evs?.hp ?? 0;
    pokemon.baseMaxhp = Math.floor((Math.floor(2 * hpBaseStat + hpIV + Math.floor(hpEV / 4) + 100) * pokemon.level) / 100 + 10);
    pokemon.maxhp = pokemon.volatiles?.["dynamax"] ? 2 * pokemon.baseMaxhp : pokemon.baseMaxhp;
    pokemon.hp = pokemon.maxhp;
    this.add("-heal", pokemon, pokemon.getHealth, "[from] ability: Minazuki");
    this.effect.ensureAura.call(this, pokemon, true);
    this.effect.restoreAlly.call(this, pokemon);
    this.effect.applyMinazukiField.call(this, pokemon);
    return 0;
  },
  onStart(pokemon) {
    this.add("-ability", pokemon, "Minazuki");
    this.effect.ensureAura.call(this, pokemon, this.effect.isUnohanaBankai.call(this, pokemon));
  },
  onSwitchIn(pokemon) {
    this.effect.ensureAura.call(this, pokemon, this.effect.isUnohanaBankai.call(this, pokemon));
  },
  onDamagePriority: -100,
  onDamage(damage, target, source, effect) {
    if (!target || target.fainted || !target.hp || typeof damage !== "number") return;
    if (!target.hasAbility("minazuki") || target.transformed) return;
    if (!this.effect.isUnohana.call(this, target)) return;
    if (this.effect.isUnohanaBankai.call(this, target) || target.bleachCaptainAwakened) {
      this.effect.markBankaiEmergencyExit.call(this, target, damage);
      return;
    }
    if (target.hp - damage > target.maxhp * 0.30) return;
    return this.effect.awaken.call(this, target);
  },
  onAfterMoveSecondary(target, source, move) {
    const pokemon = this.effectState.target;
    if (!pokemon || !pokemon.m?.unohanaEmergencyExitPending) return;
    pokemon.m.unohanaEmergencyExitPending = false;
    if (!pokemon.hasAbility("minazuki") || pokemon.transformed) return;
    if (!this.effect.isUnohana.call(this, pokemon) || !this.effect.isUnohanaBankai.call(this, pokemon)) return;
    if (!pokemon.hp || pokemon.fainted || pokemon.hp > pokemon.maxhp * 0.30) return;
    this.effect.triggerBankaiEmergencyExit.call(this, pokemon);
  },
  onResidualOrder: 28,
  onResidual(pokemon) {
    if (!pokemon || pokemon.fainted || !pokemon.hp || !pokemon.hasAbility("minazuki")) return;
    const bankai = this.effect.isUnohanaBankai.call(this, pokemon);
    this.effect.ensureAura.call(this, pokemon, bankai);
    if (!bankai && this.effect.isUnohana.call(this, pokemon) && pokemon.hp <= pokemon.maxhp * 0.30) {
      this.effect.awaken.call(this, pokemon);
      return;
    }
    this.effect.applyTeamBerry.call(this, pokemon, bankai);
    if (bankai) this.effect.applyMinazukiField.call(this, pokemon);
  }
}
