import { describe, it, expect, vi } from 'vitest';

// ─── Test: AttunementsTab barrel export ───────────────────────────────────────

describe('AttunementsTab module structure', () => {
  it('exports AttunementsTab from barrel index', async () => {
    const mod = await import('./AttunementsTab');
    expect(mod.AttunementsTab).toBeDefined();
    expect(typeof mod.AttunementsTab).toBe('function');
  });

  it('AttunementsTab has correct displayName', async () => {
    const { AttunementsTab } = await import('./AttunementsTab');
    expect(AttunementsTab.displayName).toBe('AttunementsTab');
  });
});

// ─── Test: Barrel export includes AttunementsTab ──────────────────────────────

describe('Tab barrel export', () => {
  it('includes AttunementsTab in the tabs index', async () => {
    const mod = await import('@/components/game/tabs');
    expect(mod.AttunementsTab).toBeDefined();
    expect(typeof mod.AttunementsTab).toBe('function');
  });
});

// ─── Test: Attunement data integrity ──────────────────────────────────────────

describe('Attunement data', () => {
  it('all attunements have required fields', async () => {
    const { ATTUNEMENTS_DEF } = await import('@/lib/game/data/attunements');
    for (const [id, def] of Object.entries(ATTUNEMENTS_DEF)) {
      expect(def.id).toBe(id);
      expect(def.name).toBeTruthy();
      expect(def.desc).toBeTruthy();
      expect(def.slot).toBeTruthy();
      expect(def.icon).toBeTruthy();
      expect(def.color).toBeTruthy();
      expect(def.rawManaRegen).toBeGreaterThanOrEqual(0);
      expect(def.conversionRate).toBeGreaterThanOrEqual(0);
      expect(def.capabilities.length).toBeGreaterThan(0);
      expect(def.skillCategories.length).toBeGreaterThan(0);
    }
  });

  it('enchanter is unlocked by default', async () => {
    const { ATTUNEMENTS_DEF } = await import('@/lib/game/data/attunements');
    expect(ATTUNEMENTS_DEF.enchanter.unlocked).toBe(true);
  });

  it('invoker and fabricator are locked by default', async () => {
    const { ATTUNEMENTS_DEF } = await import('@/lib/game/data/attunements');
    expect(ATTUNEMENTS_DEF.invoker.unlocked).toBe(false);
    expect(ATTUNEMENTS_DEF.fabricator.unlocked).toBe(false);
  });

  it('each attunement has a unique slot', async () => {
    const { ATTUNEMENTS_DEF } = await import('@/lib/game/data/attunements');
    const slots = Object.values(ATTUNEMENTS_DEF).map((d) => d.slot);
    const uniqueSlots = new Set(slots);
    expect(uniqueSlots.size).toBe(slots.length);
  });
});

// ─── Test: XP curve ───────────────────────────────────────────────────────────

describe('Attunement XP curve', () => {
  it('level 1 requires 0 XP', async () => {
    const { getAttunementXPForLevel } = await import('@/lib/game/data/attunements');
    expect(getAttunementXPForLevel(1)).toBe(0);
  });

  it('level 2 requires 1000 XP', async () => {
    const { getAttunementXPForLevel } = await import('@/lib/game/data/attunements');
    expect(getAttunementXPForLevel(2)).toBe(1000);
  });

  it('XP requirements increase with level', async () => {
    const { getAttunementXPForLevel } = await import('@/lib/game/data/attunements');
    const xp2 = getAttunementXPForLevel(2);
    const xp3 = getAttunementXPForLevel(3);
    const xp4 = getAttunementXPForLevel(4);
    expect(xp3).toBeGreaterThan(xp2);
    expect(xp4).toBeGreaterThan(xp3);
  });

  it('MAX_ATTUNEMENT_LEVEL is 10', async () => {
    const { MAX_ATTUNEMENT_LEVEL } = await import('@/lib/game/data/attunements');
    expect(MAX_ATTUNEMENT_LEVEL).toBe(10);
  });
});

// ─── Test: Attunement store interactions ──────────────────────────────────────

describe('Attunement store interactions', () => {
  it('addAttunementXP is callable', async () => {
    const mockAddXP = await vi.fn();
    mockAddXP('enchanter', 100);
    expect(mockAddXP).toHaveBeenCalledWith('enchanter', 100);
  });

  it('debugUnlockAttunement is callable', async () => {
    const mockUnlock = await vi.fn();
    mockUnlock('invoker');
    expect(mockUnlock).toHaveBeenCalledWith('invoker');
  });

  it('setAttunements is callable', async () => {
    const mockSet = await vi.fn();
    mockSet({ enchanter: { id: 'enchanter', active: true, level: 1, experience: 0 } });
    expect(mockSet).toHaveBeenCalled();
  });

  it('resetAttunements is callable', async () => {
    const mockReset = await vi.fn();
    mockReset();
    expect(mockReset).toHaveBeenCalledTimes(1);
  });
});

// ─── Test: Slot name mapping ──────────────────────────────────────────────────

describe('Attunement slot names', () => {
  it('all slots used by attunements have display names', async () => {
    const { ATTUNEMENTS_DEF, ATTUNEMENT_SLOT_NAMES } = await import('@/lib/game/data/attunements');
    for (const def of Object.values(ATTUNEMENTS_DEF)) {
      expect(ATTUNEMENT_SLOT_NAMES[def.slot]).toBeDefined();
      expect(ATTUNEMENT_SLOT_NAMES[def.slot].length).toBeGreaterThan(0);
    }
  });
});

// ─── Test: File size limit ────────────────────────────────────────────────────

describe('File size limits (400 lines max)', () => {
  it('AttunementsTab.tsx is under 400 lines', async () => {
    const fs = await import('fs');
    const path = await import('path');
    const filePath = path.join(__dirname, 'AttunementsTab.tsx');
    const content = fs.readFileSync(filePath, 'utf-8');
    const lines = content.split('\n').length;
    expect(lines).toBeLessThan(400);
  });
});
