import type { HealerClassId, MemberId, PartyMember } from "../types";
import type { AiCombatantId } from "../partyCombat";
import { GEAR_RECIPES, GEAR_SLOT_ORDER, type GearOwnerId, type GearProgress } from "./gear";
import { ACTIVE_INFUSIONS, activeInfusionUnlocked } from "./infusions";

export interface MemberGearModifiers {
  maxHealth: number;
  moveSpeed: number;
  healingPower: number;
  damage: number;
  cooldown: number;
  hazardDamageTaken: number;
  stunDuration: number;
}

export type EncounterGearModifiers = Record<MemberId, MemberGearModifiers>;

export const EMPTY_MEMBER_GEAR_MODIFIERS: MemberGearModifiers = {
  maxHealth: 1,
  moveSpeed: 1,
  healingPower: 1,
  damage: 1,
  cooldown: 1,
  hazardDamageTaken: 1,
  stunDuration: 1,
};

export function createEncounterGearModifiers(progress: GearProgress, healerClassId: HealerClassId): EncounterGearModifiers {
  return {
    aelia: modifiersForOwner(progress, healerClassId),
    brann: modifiersForOwner(progress, "brann"),
    nia: modifiersForOwner(progress, "nia"),
    orin: modifiersForOwner(progress, "orin"),
    vale: modifiersForOwner(progress, "vale"),
  };
}

export function applyGearHealth(party: PartyMember[], modifiers: EncounterGearModifiers): PartyMember[] {
  return party.map((member) => {
    const maxHp = Math.round(member.maxHp * modifiers[member.id].maxHealth);
    return { ...member, maxHp, hp: maxHp };
  });
}

export function aiCombatModifiers(modifiers: EncounterGearModifiers): Record<AiCombatantId, Pick<MemberGearModifiers, "damage" | "cooldown">> {
  return {
    brann: modifiers.brann,
    nia: modifiers.nia,
    orin: modifiers.orin,
    vale: modifiers.vale,
  };
}

function modifiersForOwner(progress: GearProgress, ownerId: GearOwnerId): MemberGearModifiers {
  const result = { ...EMPTY_MEMBER_GEAR_MODIFIERS };
  for (const slotId of GEAR_SLOT_ORDER) {
    const level = progress[ownerId].slots[slotId].level;
    if (level <= 0) continue;
    const statId = GEAR_RECIPES[ownerId][slotId].statId;
    if (statId === "maxHealth") result.maxHealth *= 1 + level * 0.04;
    else if (statId === "moveSpeed") result.moveSpeed *= 1 + level * 0.025;
    else if (statId === "healingPower") result.healingPower *= 1 + level * 0.04;
    else if (statId === "damage") result.damage *= 1 + level * 0.04;
    else if (statId === "attackCooldown") result.cooldown *= 1 - level * 0.03;
    else if (statId === "hazardDamageTaken") result.hazardDamageTaken *= 1 - level * 0.03;
    else if (statId === "stunResist") result.stunDuration *= Math.max(0, 1 - level * 0.08);
  }
  const ownerProgress = progress[ownerId];
  const infusion = ownerProgress.infusionAbilityId ? ACTIVE_INFUSIONS[ownerProgress.infusionAbilityId] : undefined;
  if (infusion?.ownerId === ownerId && activeInfusionUnlocked(ownerProgress)) {
    if (infusion.effectKey === "max-health") result.maxHealth *= 1.08;
    else if (infusion.effectKey === "move-speed") result.moveSpeed *= 1.08;
    else if (infusion.effectKey === "healing-power") result.healingPower *= 1.08;
    else if (infusion.effectKey === "damage") result.damage *= 1.08;
    else if (infusion.effectKey === "cooldown") result.cooldown *= 0.92;
    else if (infusion.effectKey === "hazard-shield") result.hazardDamageTaken *= 0.85;
    else if (infusion.effectKey === "stun-immune") result.stunDuration = 0;
  }
  return result;
}
