import { describe, it, expect, beforeEach } from 'vitest';
import { useManaStore, makeInitialElements } from '../stores/manaStore';
import { ErrorCode } from '../utils/result';

function resetManaStore() {
  useManaStore.setState({
    rawMana: 100,
    meditateTicks: 0,
    totalManaGathered: 0,
    elements: makeInitialElements(50, {}),
  });
}

describe('ManaStore', () => {
  beforeEach(resetManaStore);

  describe('setRawMana', () => {
    it('should set raw mana to a positive value', () => {
      useManaStore.getState().setRawMana(50);
      expect(useManaStore.getState().rawMana).toBe(50);
    });

    it('should clamp negative values to 0', () => {
      useManaStore.getState().setRawMana(-10);
      expect(useManaStore.getState().rawMana).toBe(0);
    });
  });

  describe('addRawMana', () => {
    it('should add raw mana up to max', () => {
      useManaStore.getState().addRawMana(50, 200);
      expect(useManaStore.getState().rawMana).toBe(150);
    });

    it('should cap at max mana', () => {
      useManaStore.getState().addRawMana(200, 150);
      expect(useManaStore.getState().rawMana).toBe(150);
    });

    it('should increment totalManaGathered', () => {
      useManaStore.getState().addRawMana(50, 200);
      expect(useManaStore.getState().totalManaGathered).toBe(50);
    });
  });

  describe('spendRawMana', () => {
    it('should return true and deduct when sufficient', () => {
      const result = useManaStore.getState().spendRawMana(30);
      expect(result).toBe(true);
      expect(useManaStore.getState().rawMana).toBe(70);
    });

    it('should return false when insufficient', () => {
      const result = useManaStore.getState().spendRawMana(200);
      expect(result).toBe(false);
      expect(useManaStore.getState().rawMana).toBe(100);
    });
  });

  describe('gatherMana', () => {
    it('should add mana and track total gathered', () => {
      useManaStore.getState().gatherMana(5, 200);
      expect(useManaStore.getState().rawMana).toBe(105);
      expect(useManaStore.getState().totalManaGathered).toBe(5);
    });

    it('should cap at max mana', () => {
      useManaStore.getState().gatherMana(200, 150);
      expect(useManaStore.getState().rawMana).toBe(150);
    });
  });

  describe('unlockElement', () => {
    it('should unlock element and deduct cost', () => {
      const result = useManaStore.getState().unlockElement('fire', 50);
      expect(result.success).toBe(true);
      expect(useManaStore.getState().rawMana).toBe(50);
      expect(useManaStore.getState().elements.fire.unlocked).toBe(true);
    });

    it('should fail when already unlocked', () => {
      const result = useManaStore.getState().unlockElement('transference', 0);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.code).toBe(ErrorCode.INVALID_INPUT);
      }
    });

    it('should fail when insufficient mana', () => {
      const result = useManaStore.getState().unlockElement('fire', 200);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.code).toBe(ErrorCode.INSUFFICIENT_MANA);
      }
    });
  });

  describe('addElementMana / spendElementMana', () => {
    it('should add element mana up to max', () => {
      useManaStore.getState().addElementMana('transference', 10, 50);
      expect(useManaStore.getState().elements.transference.current).toBe(10);
    });

    it('should cap at max', () => {
      useManaStore.getState().addElementMana('transference', 100, 50);
      expect(useManaStore.getState().elements.transference.current).toBe(50);
    });

    it('should deduct element mana when sufficient', () => {
      useManaStore.getState().addElementMana('transference', 20, 50);
      const result = useManaStore.getState().spendElementMana('transference', 10);
      expect(result.success).toBe(true);
      expect(useManaStore.getState().elements.transference.current).toBe(10);
    });

    it('should fail when insufficient element mana', () => {
      const result = useManaStore.getState().spendElementMana('transference', 10);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.code).toBe(ErrorCode.INSUFFICIENT_MANA);
      }
    });
  });

  describe('resetMana', () => {
    it('should reset to initial state for new loop', () => {
      useManaStore.getState().resetMana({});
      expect(useManaStore.getState().rawMana).toBe(10);
      expect(useManaStore.getState().meditateTicks).toBe(0);
      expect(useManaStore.getState().totalManaGathered).toBe(0);
    });

    it('should apply prestige upgrades for starting mana', () => {
      useManaStore.getState().resetMana({ quickStart: 5 });
      expect(useManaStore.getState().rawMana).toBe(10 + 5 * 10);
    });
  });
});
