// ─── 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 { GameState, EquipmentInstance } from './types';
import { ENCHANTMENT_EFFECTS } from './data/enchantment-effects';
import { computeEffects } from './effects/upgrade-effects';
import { hasSpecial, SPECIAL_EFFECTS } from './effects/special-effects';
import { computeDisciplineEffects } from './effects/discipline-effects';
import type { ComputedEffects } from './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 };
}

// ─── Discipline Effects Integration ──────────────────────────────────────────

export function getDisciplineEffects(state: GameState) {
  return computeDisciplineEffects(state);
}

// ─── 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>;
}

export function computeAllEffects(
  skillUpgrades: Record<string, string[]>,
  skillTiers: Record<string, number>,
  equipmentInstances: Record<string, EquipmentInstance>,
  equippedInstances: Record<string, string | null>,
  gameState: GameState
): UnifiedEffects {
  const upgradeEffects = computeEffects(skillUpgrades, skillTiers);
  const equipmentEffects = computeEquipmentEffects(equipmentInstances, equippedInstances, upgradeEffects.enchantmentPowerMultiplier);
  const disciplineEffects = getDisciplineEffects(gameState);

  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 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,
    maxManaMultiplier: upgradeEffects.maxManaMultiplier * (equipmentEffects.multipliers.maxMana || 1),
    regenMultiplier: upgradeEffects.regenMultiplier * (equipmentEffects.multipliers.regen || 1),
    clickManaMultiplier: upgradeEffects.clickManaMultiplier * (equipmentEffects.multipliers.clickMana || 1),
    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,
  };

  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);
  }

  return merged;
}

export function getUnifiedEffects(state: Pick<GameState, 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances' | 'disciplines'>): UnifiedEffects {
  return computeAllEffects(
    state.skillUpgrades || {},
    state.skillTiers || {},
    state.equipmentInstances || {},
    state.equippedInstances || {},
    state as GameState
  );
}

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

export function computeTotalMaxMana(
  state: Pick<GameState, 'skills' | 'prestigeUpgrades' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances'>,
  effects?: UnifiedEffects
): number {
  const pu = state.prestigeUpgrades;
  const skillMult = effects?.skillLevelMultiplier || 1;
  const base = 100 + ((state.skills || {}).manaWell || 0) * 100 * skillMult + ((pu || {}).manaWell || 0) * 500;
  if (!effects) effects = getUnifiedEffects(state as any);
  return Math.floor((base + effects.maxManaBonus) * effects.maxManaMultiplier);
}

export function computeTotalRegen(
  state: Pick<GameState, 'skills' | 'prestigeUpgrades' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances'>,
  effects?: UnifiedEffects
): number {
  const pu = state.prestigeUpgrades;
  const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1;
  const skillMult = effects?.skillLevelMultiplier || 1;
  const base = 2 + (state.skills.manaFlow || 0) * 1 * skillMult + (state.skills.manaSpring || 0) * 2 * skillMult + (pu.manaFlow || 0) * 0.5;
  let regen = base * temporalBonus;
  if (!effects) effects = getUnifiedEffects(state as any);
  regen = (regen + effects.regenBonus + effects.permanentRegenBonus) * effects.regenMultiplier;
  return regen;
}

export function computeTotalClickMana(
  state: Pick<GameState, 'skills' | 'skillUpgrades' | 'skillTiers' | 'equipmentInstances' | 'equippedInstances'>,
  effects?: UnifiedEffects
): number {
  const skillMult = effects?.skillLevelMultiplier || 1;
  const base = 1 + (state.skills.manaTap || 0) * 1 * skillMult + (state.skills.manaSurge || 0) * 3 * skillMult;
  if (!effects) effects = getUnifiedEffects(state as any);
  return Math.floor((base + effects.clickManaBonus) * effects.clickManaMultiplier);
}