import { describe, it, expect } from 'vitest';
import { computeConversionRates } from '../utils/conversion-rates';

// ═══════════════════════════════════════════════════════════════════════════════
// REGRESSION TEST: Elemental mana conversions incorrectly paused (Bug #348)
//
// Two root causes:
//   1. rawGrossRegen passed to computeConversionRates was ~2/hr (base only)
//      instead of actual regen including attunement contributions (3000+/hr)
//   2. grossRegen per-element used conversionRate (0.2) instead of
//      rawManaRegen (0.5) with level scaling
//
// This test verifies that conversions are NOT paused when rawGrossRegen
// is sufficient, and that per-element grossRegen uses rawManaRegen.
// ═══════════════════════════════════════════════════════════════════════════════

describe('Bug #348 — conversion pause regression', () => {
  describe('Bug 1: rawGrossRegen must include attunement regen', () => {
    it('should NOT pause base element conversions when rawGrossRegen is sufficient', () => {
      // Simulate a player with enchanter attunement providing ~3342/hr raw regen
      const rawGrossRegen = 3342.95;

      const disciplineEffects = {
        bonuses: { conversion_earth: 22.04 },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          earth: { rate: 22.04, sourceManaTypes: ['raw'] },
        },
      };

      const result = computeConversionRates({
        disciplineEffects: disciplineEffects as any,
        attunements: { enchanter: { active: true, level: 5 } },
        signedPacts: [],
        pactElementMap: {},
        invokerLevel: 0,
        meditationMultiplier: 1,
        grossRegen: { transference: 0.5, earth: 0.4 },
        rawGrossRegen,
      });

      // Earth conversion: baseRate=22.04, rawCost=2
      // rawDrain = 22.04 * 1.0 * 1.0 * 1.0 * 2 = 44.08/hr
      // 44.08 < 3342.95 => should NOT be paused
      const earthEntry = result.rates['earth'];
      expect(earthEntry).toBeDefined();
      expect(earthEntry.paused).toBe(false);
      expect(earthEntry.finalRate).toBeGreaterThan(0);
    });

    it('should pause conversions when rawGrossRegen is truly insufficient', () => {
      // Simulate the bug: rawGrossRegen is only base 2/hr
      const rawGrossRegen = 2.0;

      const disciplineEffects = {
        bonuses: { conversion_earth: 22.04 },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          earth: { rate: 22.04, sourceManaTypes: ['raw'] },
        },
      };

      const result = computeConversionRates({
        disciplineEffects: disciplineEffects as any,
        attunements: {},
        signedPacts: [],
        pactElementMap: {},
        invokerLevel: 0,
        meditationMultiplier: 1,
        grossRegen: {},
        rawGrossRegen,
      });

      // With only 2/hr raw regen, earth conversion (needing ~2204/hr) should be paused
      const earthEntry = result.rates['earth'];
      expect(earthEntry).toBeDefined();
      expect(earthEntry.paused).toBe(true);
      expect(earthEntry.finalRate).toBe(0);
    });

    it('should produce correct finalRate for earth with high rawGrossRegen', () => {
      const rawGrossRegen = 5000;

      const disciplineEffects = {
        bonuses: { conversion_earth: 22.04 },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          earth: { rate: 22.04, sourceManaTypes: ['raw'] },
        },
      };

      const result = computeConversionRates({
        disciplineEffects: disciplineEffects as any,
        attunements: { fabricator: { active: true, level: 1 } },
        signedPacts: [],
        pactElementMap: {},
        invokerLevel: 0,
        meditationMultiplier: 1,
        grossRegen: { earth: 0.4 },
        rawGrossRegen,
      });

      const earthEntry = result.rates['earth'];
      expect(earthEntry.paused).toBe(false);
      // baseRate = 22.04 (discipline) + 0.25 (ATTUNEMENT_BASE_RATES earth) = 22.29
      // attMult = 1 + (1.5^(1-1) - 1) = 1
      // pactMult = 1, medMult = 1
      // finalRate = 22.29 * 1 * 1 * 1 = 22.29
      expect(earthEntry.finalRate).toBeCloseTo(22.29, 1);
    });
  });

  describe('Bug 2: grossRegen per-element must use rawManaRegen with level scaling', () => {
    it('should NOT pause composite conversions when component grossRegen is sufficient', () => {
      // Metal = Fire + Earth. If fire grossRegen is high enough, metal should not pause.
      const disciplineEffects = {
        bonuses: { conversion_fire: 10, conversion_metal: 5 },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          fire: { rate: 10, sourceManaTypes: ['raw'] },
          metal: { rate: 5, sourceManaTypes: ['raw'] },
        },
      };

      // Use rawManaRegen values (0.5 for enchanter at level 1) not conversionRate (0.2)
      const result = computeConversionRates({
        disciplineEffects: disciplineEffects as any,
        attunements: { enchanter: { active: true, level: 1 } },
        signedPacts: [],
        pactElementMap: {},
        invokerLevel: 0,
        meditationMultiplier: 1,
        grossRegen: { transference: 0.5 }, // rawManaRegen for enchanter level 1
        rawGrossRegen: 10000,
      });

      // Fire conversion should not be paused (rawGrossRegen is 10000, fire rawDrain = 10*10 = 100)
      const fireEntry = result.rates['fire'];
      expect(fireEntry.paused).toBe(false);
      expect(fireEntry.finalRate).toBeGreaterThan(0);
    });

    it('should correctly compute grossRegen with level scaling', () => {
      // Enchanter level 3: rawManaRegen = 0.5 * 1.5^(3-1) = 0.5 * 2.25 = 1.125
      const disciplineEffects = {
        bonuses: {},
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {},
      };

      const result = computeConversionRates({
        disciplineEffects: disciplineEffects as any,
        attunements: { enchanter: { active: true, level: 3 } },
        signedPacts: [],
        pactElementMap: {},
        invokerLevel: 0,
        meditationMultiplier: 1,
        grossRegen: { transference: 1.125 }, // 0.5 * 1.5^2
        rawGrossRegen: 10000,
      });

      // With no discipline conversions, nothing should be paused
      for (const [elem, entry] of Object.entries(result.rates)) {
        if (entry.baseRate > 0) {
          expect(entry.paused).toBe(false);
        }
      }
    });

    it('should pause composite when component grossRegen is truly insufficient', () => {
      // Metal = Fire + Earth. If fire grossRegen is 0, metal should pause.
      const disciplineEffects = {
        bonuses: { conversion_fire: 10, conversion_metal: 5 },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          fire: { rate: 10, sourceManaTypes: ['raw'] },
          metal: { rate: 5, sourceManaTypes: ['raw'] },
        },
      };

      const result = computeConversionRates({
        disciplineEffects: disciplineEffects as any,
        attunements: {},
        signedPacts: [],
        pactElementMap: {},
        invokerLevel: 0,
        meditationMultiplier: 1,
        grossRegen: {}, // No component regen at all
        rawGrossRegen: 10000, // Raw is sufficient
      });

      // Metal needs fire and earth as components. With no grossRegen for either,
      // metal should be paused due to insufficient component regen.
      const metalEntry = result.rates['metal'];
      expect(metalEntry.paused).toBe(true);
      expect(metalEntry.pauseReason).toContain('Insufficient');
    });
  });

  describe('End-to-end: both fixes combined', () => {
    it('should produce non-zero conversion rates for all base elements with proper setup', () => {
      // Simulate a mid-game player with:
      // - Enchanter level 5 (rawManaRegen = 0.5 * 1.5^4 ≈ 2.53)
      // - Fabricator level 3 (rawManaRegen = 0.4 * 1.5^2 = 0.9)
      // - Total attunement regen ≈ 3.43/hr + base 2/hr = ~5.43/hr
      // But with discipline bonuses providing high conversion rates
      const rawGrossRegen = 5000; // Simulating high raw regen from all sources

      const disciplineEffects = {
        bonuses: {
          conversion_fire: 15,
          conversion_water: 15,
          conversion_air: 15,
          conversion_earth: 15,
        },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          fire: { rate: 15, sourceManaTypes: ['raw'] },
          water: { rate: 15, sourceManaTypes: ['raw'] },
          air: { rate: 15, sourceManaTypes: ['raw'] },
          earth: { rate: 15, sourceManaTypes: ['raw'] },
        },
      };

      const result = computeConversionRates({
        disciplineEffects: disciplineEffects as any,
        attunements: {
          enchanter: { active: true, level: 5 },
          fabricator: { active: true, level: 3 },
        },
        signedPacts: [],
        pactElementMap: {},
        invokerLevel: 0,
        meditationMultiplier: 1,
        grossRegen: {
          transference: 2.53, // 0.5 * 1.5^4
          earth: 0.9,         // 0.4 * 1.5^2
        },
        rawGrossRegen,
      });

      // All base element conversions should be active
      for (const elem of ['fire', 'water', 'air', 'earth']) {
        const entry = result.rates[elem];
        expect(entry).toBeDefined();
        expect(entry.paused).toBe(false);
        expect(entry.finalRate).toBeGreaterThan(0);
      }

      // totalRawDrain should be non-zero (conversions are consuming raw mana)
      expect(result.totalRawDrain).toBeGreaterThan(0);
    });
  });
});
