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

// ═══════════════════════════════════════════════════════════════════════════════
// MANA CONVERSION: COMPONENT CONSUMPTION DEDUCTION TESTS
// Bug #293: elementDrain computed but never subtracted from element pools
// ═══════════════════════════════════════════════════════════════════════════════

describe('Mana Conversion — component consumption deduction (bug #293)', () => {
  describe('computeConversionRates elementDrain', () => {
    it('should compute non-zero elementDrain for elements used as components', () => {
      const disciplineEffects = {
        bonuses: { conversion_fire: 0.5, conversion_metal: 0.35 },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          fire: { rate: 0.5, sourceManaTypes: ['raw'] },
          metal: { rate: 0.35, sourceManaTypes: ['raw'] },
        },
      };

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

      // Fire is used as a component for metal conversion
      // metal rate = 0.35, fire component cost = 6 per unit (3 * distance 2)
      // elementDrain[fire] = 0.35 * 6 = 2.1/hr
      expect(result.elementDrain['fire']).toBeGreaterThan(0);
      expect(result.elementDrain['fire']).toBeCloseTo(0.35 * 6, 5);

      // Earth is also used as a component for metal conversion
      expect(result.elementDrain['earth']).toBeGreaterThan(0);
      expect(result.elementDrain['earth']).toBeCloseTo(0.35 * 6, 5);
    });

    it('should compute elementRegen as produced - drained', () => {
      const disciplineEffects = {
        bonuses: { conversion_fire: 0.5, conversion_metal: 0.35 },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          fire: { rate: 0.5, sourceManaTypes: ['raw'] },
          metal: { rate: 0.35, sourceManaTypes: ['raw'] },
        },
      };

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

      // Fire: produced = 0.5/hr, drained = 0.35 * 6 = 2.1/hr
      const fireEntry = result.rates['fire'];
      expect(fireEntry.finalRate).toBeCloseTo(0.5, 5);

      // Metal: produced = 0.35/hr, no drain (nothing consumes metal as component)
      const metalEntry = result.rates['metal'];
      expect(metalEntry.finalRate).toBeCloseTo(0.35, 5);

      // Verify net: produced - drained
      const fireProduced = fireEntry.finalRate;
      const fireDrained = result.elementDrain['fire'] || 0;
      expect(fireProduced - fireDrained).toBeCloseTo(0.5 - 2.1, 5);
    });

    it('should have zero elementDrain when element is not used as component', () => {
      const disciplineEffects = {
        bonuses: { conversion_fire: 0.5 },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          fire: { rate: 0.5, sourceManaTypes: ['raw'] },
        },
      };

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

      // Fire is not used as a component by any active conversion
      expect(result.elementDrain['fire']).toBe(0);
    });

    it('should compute correct net regen for downstream elements', () => {
      // Test the full chain: fire+earth -> metal, fire+air -> lightning
      // Both metal and lightning consume fire as a component
      const disciplineEffects = {
        bonuses: {
          conversion_fire: 0.5,
          conversion_metal: 0.35,
          conversion_lightning: 0.35,
        },
        multipliers: {},
        specials: new Set<string>(),
        meditationCapBonus: 0,
        conversions: {
          fire: { rate: 0.5, sourceManaTypes: ['raw'] },
          metal: { rate: 0.35, sourceManaTypes: ['raw'] },
          lightning: { rate: 0.35, sourceManaTypes: ['raw'] },
        },
      };

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

      // Fire: produced = 0.5, drained by metal (0.35 * 6 = 2.1) and lightning (0.35 * 6 = 2.1)
      // Total fire drain = 2.1 + 2.1 = 4.2
      expect(result.elementDrain['fire']).toBeCloseTo(4.2, 5);

      // Earth: produced = 0 (no earth discipline), drained by metal (0.35 * 6 = 2.1)
      expect(result.elementDrain['earth']).toBeCloseTo(2.1, 5);

      // Air: produced = 0 (no air discipline), drained by lightning (0.35 * 6 = 2.1)
      expect(result.elementDrain['air']).toBeCloseTo(2.1, 5);

      // Metal: produced = 0.35, not consumed by anything in this setup
      expect(result.elementDrain['metal'] || 0).toBe(0);

      // Lightning: produced = 0.35, not consumed by anything in this setup
      expect(result.elementDrain['lightning'] || 0).toBe(0);
    });
  });
});
