// ─── Mana & Regen Utilities ──────────────────────────────────────────────────

import type { AttunementState } from '../types';
import type { ComputedEffects } from '../effects/upgrade-effects.types';
import { HOURS_PER_TICK } from '../constants';
import { getTotalAttunementRegen, getTotalAttunementConversionDrain } from '../data/attunements';

export interface DisciplineBonuses {
  bonuses: Record<string, number>;
  multipliers: Record<string, number>;
}

// ─── Mana Params ────────────────────────────────────────────────────────────

export interface ManaComputeParams {
  skills: Record<string, number>;
  prestigeUpgrades: Record<string, number>;
  skillUpgrades?: Record<string, string[]>;
  skillTiers?: Record<string, number>;
}

export interface RegenComputeParams extends ManaComputeParams {
  attunements: Record<string, AttunementState>;
}

export interface EffectiveRegenParams extends RegenComputeParams {
  rawMana: number;
  incursionStrength: number;
}

// ─── Max Mana ────────────────────────────────────────────────────────────────

export function computeMaxMana(
  state: Pick<ManaComputeParams, 'skills' | 'prestigeUpgrades'> & Partial<Pick<ManaComputeParams, 'skillUpgrades' | 'skillTiers'>>,
  effects?: ComputedEffects,
  discipline?: DisciplineBonuses,
): number {
  const pu = state.prestigeUpgrades;
  const base =
    100 +
    ((state.skills || {}).manaWell || 0) * 100 +
    ((pu || {}).manaWell || 0) * 500 +
    (discipline?.bonuses?.maxManaBonus || 0);

  if (effects) {
    return Math.floor((base + effects.maxManaBonus) * effects.maxManaMultiplier);
  }
  return base;
}

// ─── Regen ────────────────────────────────────────────────────────────────────

export function computeRegen(
  state: Pick<RegenComputeParams, 'skills' | 'prestigeUpgrades' | 'attunements'> & Partial<Pick<RegenComputeParams, 'skillUpgrades' | 'skillTiers'>>,
  effects?: ComputedEffects,
  discipline?: DisciplineBonuses,
): number {
  const pu = state.prestigeUpgrades;
  const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1;
  const base =
    2 +
    ((state.skills || {}).manaFlow || 0) * 1 +
    ((state.skills || {}).manaSpring || 0) * 2 +
    ((pu || {}).manaFlow || 0) * 0.5;

  let regen = base * temporalBonus;

  // Add attunement raw mana regen
  const attunementRegen = getTotalAttunementRegen(state.attunements || {});
  regen += attunementRegen;

  // Apply discipline regen bonus
  if (discipline?.bonuses?.regenBonus) {
    regen += discipline.bonuses.regenBonus;
  }

  // Apply upgrade effects if provided
  if (effects) {
    regen = (regen + effects.regenBonus + effects.permanentRegenBonus) * effects.regenMultiplier;
  }

  return regen;
}

// ─── Effective Regen for Display ──────────────────────────────────────────────

export function computeEffectiveRegenForDisplay(
  state: Pick<RegenComputeParams, 'skills' | 'prestigeUpgrades' | 'attunements'>,
  effects?: ComputedEffects,
  discipline?: DisciplineBonuses,
): { rawRegen: number; conversionDrain: number; effectiveRegen: number } {
  const rawRegen = computeRegen(state, effects, discipline);
  const conversionDrain = getTotalAttunementConversionDrain(state.attunements || {});
  const effectiveRegen = Math.max(0, rawRegen - conversionDrain);

  return { rawRegen, conversionDrain, effectiveRegen };
}

// ─── Effective Regen (dynamic) ────────────────────────────────────────────────

export function computeEffectiveRegen(
  state: Pick<RegenComputeParams, 'skills' | 'prestigeUpgrades' | 'attunements'> & { rawMana: number; incursionStrength: number },
  effects?: ComputedEffects,
  discipline?: DisciplineBonuses,
): number {
  let regen = computeRegen(state, effects, discipline);
  const incursionStrength = state.incursionStrength || 0;
  regen *= (1 - incursionStrength);
  return regen;
}

// ─── Click Mana ───────────────────────────────────────────────────────────────

export function computeClickMana(
  skills: Record<string, number>,
  discipline?: DisciplineBonuses,
): number {
  const skillTap = (skills.manaTap || 0) * 1;
  const skillSurge = (skills.manaSurge || 0) * 3;
  const discClickMult = discipline?.bonuses?.clickManaMultiplier || 0;

  return 1 + skillTap + skillSurge + discClickMult;
}

// ─── Meditation Bonus ─────────────────────────────────────────────────────────

export function getMeditationBonus(meditateTicks: number, skills: Record<string, number>, meditationEfficiency: number = 1): number {
  const hasMeditation = skills.meditation === 1;
  const hasDeepTrance = skills.deepTrance === 1;
  const hasVoidMeditation = skills.voidMeditation === 1;

  const hours = meditateTicks * HOURS_PER_TICK;

  // Base meditation: ramps up over 4 hours to 1.5x
  let bonus = 1 + Math.min(hours / 4, 0.5);

  // With Meditation Focus: up to 2.5x after 4 hours
  if (hasMeditation && hours >= 4) {
    bonus = 2.5;
  }

  // With Deep Trance: up to 3.0x after 6 hours
  if (hasDeepTrance && hours >= 6) {
    bonus = 3.0;
  }

  // With Void Meditation: up to 5.0x after 8 hours
  if (hasVoidMeditation && hours >= 8) {
    bonus = 5.0;
  }

  // Apply meditation efficiency from upgrades
  bonus *= meditationEfficiency;

  return bonus;
}
