// ─── Unified Effect System ─────────────────────────────────────────────────
// This module consolidates ALL effect sources into a single computation:
// - Discipline effects (from active disciplines)
// - Skill upgrade effects (from milestone upgrades)
// - Equipment enchantment effects (from enchanted gear)

import type { EquipmentInstance } from './types';
import { ENCHANTMENT_EFFECTS } from './data/enchantment-effects';
import { computeEffects } from './effects/upgrade-effects';
import { computeDisciplineEffects } from './effects/discipline-effects';
import type { ComputedEffects } from './effects/upgrade-effects.types';

// Re-export for convenience
export { computeEffects } from './effects/upgrade-effects';
export { hasSpecial, SPECIAL_EFFECTS } from './effects/special-effects';
export type { ComputedEffects } from './effects/upgrade-effects.types';

// ─── Equipment Effect Computation ────────────────────────────────────────────

export function computeEquipmentEffects(
  equipmentInstances: Record<string, EquipmentInstance>,
  equippedInstances: Record<string, string | null>,
  enchantmentPowerMultiplier: number = 1.0
): {
  bonuses: Record<string, number>;
  multipliers: Record<string, number>;
  specials: Set<string>;
} {
  const bonuses: Record<string, number> = {};
  const multipliers: Record<string, number> = {};
  const specials = new Set<string>();

  for (const instanceId of Object.values(equippedInstances || {})) {
    if (!instanceId) continue;
    const instance = equipmentInstances[instanceId];
    if (!instance) continue;

    for (const ench of instance.enchantments) {
      const effectDef = ENCHANTMENT_EFFECTS[ench.effectId];
      if (!effectDef) continue;
      const { effect } = effectDef;

      if (effect.type === 'bonus' && effect.stat && effect.value) {
        const adjustedValue = effect.value * enchantmentPowerMultiplier;
        if (effect.stat.startsWith('elementCap_')) {
          const element = effect.stat.replace('elementCap_', '');
          bonuses[`elementCap_${element}`] = (bonuses[`elementCap_${element}`] || 0) + adjustedValue * ench.stacks;
        } else {
          bonuses[effect.stat] = (bonuses[effect.stat] || 0) + adjustedValue * ench.stacks;
        }
      } else if (effect.type === 'multiplier' && effect.stat && effect.value) {
        const adjustedValue = effect.value * enchantmentPowerMultiplier;
        const key = effect.stat;
        if (!multipliers[key]) multipliers[key] = 1;
        for (let i = 0; i < ench.stacks; i++) {
          multipliers[key] *= adjustedValue;
        }
      } else if (effect.type === 'special' && effect.specialId) {
        specials.add(effect.specialId);
      }
    }
  }

  return { bonuses, multipliers, specials };
}

// ─── Unified Computed Effects ─────────────────────────────────────────────────

export interface UnifiedEffects extends ComputedEffects {
  equipmentBonuses: Record<string, number>;
  equipmentMultipliers: Record<string, number>;
  equipmentSpecials: Set<string>;
  disciplineBonuses: Record<string, number>;
  disciplineMultipliers: Record<string, number>;
  disciplineSpecials: Set<string>;
  /**
   * Total pact affinity bonus from disciplines and prestige upgrades.
   * Reduces pact signing time: effectiveTime = baseTime * (1 - pactAffinityBonus).
   * Capped at 0.9 to prevent zero/negative times.
   */
  pactAffinityBonus: number;
  /**
   * Total guardian boon multiplier from disciplines.
   * Scales the effectiveness of all guardian unique perks.
   * 1.0 = base, 1.15 = +15%, etc.
   */
  guardianBoonMultiplier: number;
}

export function computeAllEffects(
  equipmentInstances: Record<string, EquipmentInstance>,
  equippedInstances: Record<string, string | null>,
  prestigeUpgrades?: Record<string, number>,
): UnifiedEffects {
  const upgradeEffects = computeEffects();
  const steadyHandLevel = (prestigeUpgrades?.steadyHand || 0);
  const enchantmentPowerMultiplier = upgradeEffects.enchantmentPowerMultiplier * (1 + steadyHandLevel * 0.15);
  const equipmentEffects = computeEquipmentEffects(equipmentInstances, equippedInstances, enchantmentPowerMultiplier);
  const disciplineEffects = computeDisciplineEffects();

  const perElementCapBonus: Record<string, number> = { ...upgradeEffects.perElementCapBonus };
  for (const [key, value] of Object.entries(equipmentEffects.bonuses)) {
    if (key.startsWith('elementCap_')) {
      const element = key.replace('elementCap_', '');
      perElementCapBonus[element] = (perElementCapBonus[element] || 0) + value;
    }
  }

  const perElementRegenBonus: Record<string, number> = { ...upgradeEffects.perElementRegenBonus };

  // Merge per-element cap bonuses from discipline effects (elementCap_{element})
  for (const [key, value] of Object.entries(disciplineEffects.bonuses)) {
    if (key.startsWith('elementCap_')) {
      const element = key.replace('elementCap_', '');
      perElementCapBonus[element] = (perElementCapBonus[element] || 0) + value;
    }
  }

  const merged: UnifiedEffects = {
    ...upgradeEffects,
    maxManaBonus: upgradeEffects.maxManaBonus + (equipmentEffects.bonuses.maxMana || 0) + (disciplineEffects.bonuses.maxManaBonus || 0),
    regenBonus: upgradeEffects.regenBonus + (equipmentEffects.bonuses.regen || 0) + (disciplineEffects.bonuses.regenBonus || 0),
    clickManaBonus: upgradeEffects.clickManaBonus + (equipmentEffects.bonuses.clickMana || 0) + (disciplineEffects.bonuses.clickManaBonus || 0),
    baseDamageBonus: upgradeEffects.baseDamageBonus + (equipmentEffects.bonuses.baseDamage || 0) + (disciplineEffects.bonuses.baseDamageBonus || 0),
    elementCapBonus: upgradeEffects.elementCapBonus + (equipmentEffects.bonuses.elementCap || 0) + (disciplineEffects.bonuses.elementCapBonus || 0),
    perElementCapBonus,
    perElementRegenBonus,
    maxManaMultiplier: upgradeEffects.maxManaMultiplier * (equipmentEffects.multipliers.maxMana || 1),
    regenMultiplier: upgradeEffects.regenMultiplier * (equipmentEffects.multipliers.regen || 1) * (1 + (disciplineEffects.multipliers.regenMultiplier || 0)),
    clickManaMultiplier: (upgradeEffects.clickManaMultiplier * (equipmentEffects.multipliers.clickMana || 1)) * (1 + (disciplineEffects.bonuses.clickManaMultiplier || 0)),
    baseDamageMultiplier: upgradeEffects.baseDamageMultiplier * (equipmentEffects.multipliers.baseDamage || 1),
    attackSpeedMultiplier: upgradeEffects.attackSpeedMultiplier * (equipmentEffects.multipliers.attackSpeed || 1),
    elementCapMultiplier: upgradeEffects.elementCapMultiplier * (equipmentEffects.multipliers.elementCap || 1),
    specials: new Set([...Array.from(upgradeEffects.specials), ...Array.from(equipmentEffects.specials), ...Array.from(disciplineEffects.specials)]),
    equipmentBonuses: equipmentEffects.bonuses,
    equipmentMultipliers: equipmentEffects.multipliers,
    equipmentSpecials: equipmentEffects.specials,
    disciplineBonuses: disciplineEffects.bonuses,
    disciplineMultipliers: disciplineEffects.multipliers,
    disciplineSpecials: disciplineEffects.specials,
    pactAffinityBonus: Math.min(0.9, disciplineEffects.bonuses.pactAffinityBonus || 0),
    guardianBoonMultiplier: 1 + (disciplineEffects.bonuses.guardianBoonMultiplier || 0),
  };

  if (equipmentEffects.bonuses.critChance) {
    merged.critChanceBonus += equipmentEffects.bonuses.critChance;
  }
  if (equipmentEffects.bonuses.meditationEfficiency) {
    merged.meditationEfficiency *= (equipmentEffects.multipliers.meditationEfficiency || 1);
  }
  if (equipmentEffects.bonuses.studySpeed) {
    merged.studySpeedMultiplier *= (equipmentEffects.multipliers.studySpeed || 1);
  }
  if (disciplineEffects.bonuses.studySpeed) {
    merged.studySpeedMultiplier *= (1 + disciplineEffects.bonuses.studySpeed);
  }

  return merged;
}

export function getUnifiedEffects(state: {
  equipmentInstances?: Record<string, EquipmentInstance>;
  equippedInstances?: Record<string, string | null>;
  prestigeUpgrades?: Record<string, number>;
}): UnifiedEffects {
  return computeAllEffects(
    state.equipmentInstances || {},
    state.equippedInstances || {},
    state.prestigeUpgrades,
  );
}

// ─── Stat Computation with All Effects ───────────────────────────────────────

export function computeTotalMaxMana(
  state: {
    prestigeUpgrades?: Record<string, number>;
    equipmentInstances?: Record<string, EquipmentInstance>;
    equippedInstances?: Record<string, string | null>;
  },
  effects?: UnifiedEffects
): number {
  const pu = state.prestigeUpgrades;
  const base = 100 + ((pu || {}).manaWell || 0) * 500;
  const resolvedEffects = effects || getUnifiedEffects(state);
  return Math.floor((base + resolvedEffects.maxManaBonus) * resolvedEffects.maxManaMultiplier);
}

export function computeTotalRegen(
  state: {
    prestigeUpgrades?: Record<string, number>;
    equipmentInstances?: Record<string, EquipmentInstance>;
    equippedInstances?: Record<string, string | null>;
  },
  effects?: UnifiedEffects
): number {
  const pu = state.prestigeUpgrades;
  const temporalBonus = 1 + ((pu?.temporalEcho || 0)) * 0.1;
  const base = 2 + (pu?.manaFlow || 0) * 0.5;
  let regen = base * temporalBonus;
  const resolvedEffects = effects || getUnifiedEffects(state);
  regen = (regen + resolvedEffects.regenBonus + resolvedEffects.permanentRegenBonus) * resolvedEffects.regenMultiplier;
  return regen;
}

export function computeTotalClickMana(
  state: {
    equipmentInstances?: Record<string, EquipmentInstance>;
    equippedInstances?: Record<string, string | null>;
  },
  effects?: UnifiedEffects
): number {
  const base = 1;
  const resolvedEffects = effects || getUnifiedEffects(state);
  return Math.floor((base + resolvedEffects.clickManaBonus) * resolvedEffects.clickManaMultiplier);
}
