import { describe, it, expect, beforeEach } from 'vitest';
import { useDisciplineStore } from '../stores/discipline-slice';
import { useManaStore } from '../stores/manaStore';

function resetDisciplineStore() {
  useDisciplineStore.setState({
    disciplines: {},
    activeIds: [],
    concurrentLimit: 1,
    totalXP: 0,
    processedPerks: [],
    practicingCallbacks: null,
  });
}

describe('DisciplineStore — reactivate after deactivate', () => {
  beforeEach(resetDisciplineStore);

  it('should reactivate a raw discipline after deactivate when rawMana is sufficient', () => {
    // Set up mana store with sufficient raw mana
    useManaStore.setState({ rawMana: 1000, elements: {} });

    // First activation succeeds (reads rawMana from mana store)
    useDisciplineStore.getState().activate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');

    // Deactivate
    useDisciplineStore.getState().deactivate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).not.toContain('raw-mastery');
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].paused).toBe(true);

    // Reactivate — reads rawMana=1000 from mana store, should succeed
    useDisciplineStore.getState().activate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].paused).toBe(false);
  });

  it('should reactivate even with zero mana (activation is optimistic, drain applies on tick)', () => {
    // Activate with sufficient mana
    useManaStore.setState({ rawMana: 1000, elements: {} });
    useDisciplineStore.getState().activate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');

    // Build up XP via ticks
    useDisciplineStore.getState().processTick({ rawMana: 1000, elements: {} });
    useDisciplineStore.getState().processTick({ rawMana: 1000, elements: {} });
    const xp = useDisciplineStore.getState().disciplines['raw-mastery'].xp;
    expect(xp).toBeGreaterThan(0);

    // Deactivate
    useDisciplineStore.getState().deactivate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).not.toContain('raw-mastery');

    // Set rawMana to 0 — reactivation should still succeed (activation is optimistic)
    // but the discipline will auto-pause on the next tick due to insufficient mana
    useManaStore.setState({ rawMana: 0, elements: {} });
    useDisciplineStore.getState().activate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');
  });

  it('should reactivate a discipline with elements after deactivating it', () => {
    useManaStore.setState({
      rawMana: 0,
      elements: { fire: { unlocked: true, current: 100, max: 100, baseMax: 100 } },
    });

    useDisciplineStore.getState().activate('attune-fire');
    expect(useDisciplineStore.getState().activeIds).toContain('attune-fire');

    useDisciplineStore.getState().deactivate('attune-fire');
    expect(useDisciplineStore.getState().activeIds).not.toContain('attune-fire');

    // Reactivate — reads elements from mana store
    useDisciplineStore.getState().activate('attune-fire');
    expect(useDisciplineStore.getState().activeIds).toContain('attune-fire');
    expect(useDisciplineStore.getState().disciplines['attune-fire'].paused).toBe(false);
  });

  it('should auto-pause on zero mana and not accrue XP', () => {
    useManaStore.setState({ rawMana: 100, elements: {} });
    useDisciplineStore.getState().activate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');

    // Tick with no mana — discipline should auto-pause (drain model)
    useDisciplineStore.getState().processTick({ rawMana: 0, elements: {} });
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].autoPaused).toBe(true);

    // XP should NOT accrue when auto-paused
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].xp).toBe(0);
  });

  it('should preserve XP when deactivating and reactivating', () => {
    useManaStore.setState({ rawMana: 1000, elements: {} });
    useDisciplineStore.getState().activate('raw-mastery');
    useDisciplineStore.getState().processTick({ rawMana: 1000, elements: {} });
    useDisciplineStore.getState().processTick({ rawMana: 1000, elements: {} });
    useDisciplineStore.getState().processTick({ rawMana: 1000, elements: {} });
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].xp).toBe(3);

    useDisciplineStore.getState().deactivate('raw-mastery');
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].xp).toBe(3);
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].paused).toBe(true);

    useDisciplineStore.getState().activate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].xp).toBe(3);

    useDisciplineStore.getState().processTick({ rawMana: 1000, elements: {} });
    expect(useDisciplineStore.getState().disciplines['raw-mastery'].xp).toBe(4);
  });

  it('should use gameState overrides when explicitly provided (for test control)', () => {
    // Even though mana store has no mana, explicit override should work
    useManaStore.setState({ rawMana: 0, elements: {} });

    // First activation: no state yet, so canProceed returns true (optimistic)
    useDisciplineStore.getState().activate('raw-mastery');
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');

    useDisciplineStore.getState().deactivate('raw-mastery');

    // Reactivate with explicit override — bypasses store reads
    useDisciplineStore.getState().activate('raw-mastery', {
      rawMana: 1000,
      elements: {},
      signedPacts: [],
    });
    expect(useDisciplineStore.getState().activeIds).toContain('raw-mastery');
  });
});
