import type { PartyMember } from '../game'

export type PvpRoguelikeUpgradeSide<TBuff extends string, TDebuff extends string> = {
  party: PartyMember[]
  resource: number
  cooldowns: Record<string, number>
  enemyHealth: number
  buffs: TBuff[]
  debuffs: TDebuff[]
}

function removeRandomItem<T>(items: readonly T[], random = Math.random) {
  if (items.length === 0) return [...items]
  const removedIndex = Math.floor(random() * items.length)
  return items.filter((_, index) => index !== removedIndex)
}

export function recoverPartyForNextPvpRoguelikeEncounter(party: readonly PartyMember[]) {
  return party.map((member) => ({
    ...member,
    health: member.maxHealth,
    debuff: undefined,
    debuffTicks: undefined,
    poisonStacks: undefined,
    maxHealthPenaltyTicks: undefined,
    healingReductionTicks: undefined,
  }))
}

export function applyPvpRoguelikeUpgradeChoice<
  TBuff extends string,
  TDebuff extends string,
  TSide extends PvpRoguelikeUpgradeSide<TBuff, TDebuff>,
>({
  side,
  buffId,
  incomingDebuffId,
  reviveBuffId,
  random,
}: {
  side: TSide
  buffId: TBuff
  incomingDebuffId?: TDebuff
  reviveBuffId: TBuff
  random?: () => number
}) {
  const reviveSelected = buffId === reviveBuffId
  const nextBuffs = reviveSelected ? side.buffs : [...side.buffs, buffId]
  const nextDebuffs = incomingDebuffId ? [...side.debuffs, incomingDebuffId] : side.debuffs
  return {
    ...side,
    buffs: nextBuffs,
    debuffs: reviveSelected ? removeRandomItem(nextDebuffs, random) : nextDebuffs,
  }
}

export function preparePvpRoguelikeNextEncounter<
  TBuff extends string,
  TDebuff extends string,
  TSide extends PvpRoguelikeUpgradeSide<TBuff, TDebuff>,
>({
  side,
  maxResource,
  enemyMaxHealth,
}: {
  side: TSide
  maxResource: number
  enemyMaxHealth: number
}) {
  return {
    ...side,
    party: recoverPartyForNextPvpRoguelikeEncounter(side.party),
    resource: maxResource,
    cooldowns: {},
    enemyHealth: enemyMaxHealth,
  }
}
