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

// ─── Test: CraftingTab barrel export ──────────────────────────────────────────

describe('CraftingTab module structure', () => {
  it('exports CraftingTab from its module', async () => {
    // Allow extra time for the heavy component import (FabricatorSubTab/EnchanterSubTab)
    const mod = await import('./CraftingTab');
    expect(mod.CraftingTab).toBeDefined();
    expect(typeof mod.CraftingTab).toBe('function');
  }, 30000);

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

// ─── Test: CraftingTab in tabs barrel index ────────────────────────────────────

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

// ─── Test: FabricatorSubTab ────────────────────────────────────────────────────

describe('FabricatorSubTab module', () => {
  it('exports FabricatorSubTab', async () => {
    const mod = await import('./CraftingTab/FabricatorSubTab');
    expect(mod.FabricatorSubTab).toBeDefined();
    expect(typeof mod.FabricatorSubTab).toBe('function');
  });

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

// ─── Test: EnchanterSubTab ─────────────────────────────────────────────────────

describe('EnchanterSubTab module', () => {
  it('exports EnchanterSubTab', async () => {
    const mod = await import('./CraftingTab/EnchanterSubTab');
    expect(mod.EnchanterSubTab).toBeDefined();
    expect(typeof mod.EnchanterSubTab).toBe('function');
  });

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

// ─── Test: Fabricator recipes data ─────────────────────────────────────────────

describe('Fabricator recipes data', () => {
  it('exports FABRICATOR_RECIPES', async () => {
    const mod = await import('@/lib/game/data/fabricator-recipes');
    expect(mod.FABRICATOR_RECIPES).toBeDefined();
    expect(Object.keys(mod.FABRICATOR_RECIPES).length).toBeGreaterThan(0);
  });

  it('all recipes have required fields', async () => {
    const { FABRICATOR_RECIPES } = await import('@/lib/game/data/fabricator-recipes');
    for (const recipe of Object.values(FABRICATOR_RECIPES)) {
      expect(recipe.id).toBeTruthy();
      expect(recipe.name).toBeTruthy();
      expect(recipe.description).toBeTruthy();
      expect(recipe.manaType).toBeTruthy();
      expect(recipe.equipmentTypeId).toBeTruthy();
      expect(recipe.slot).toBeTruthy();
      expect(recipe.materials).toBeDefined();
      expect(recipe.manaCost).toBeGreaterThan(0);
      expect(recipe.craftTime).toBeGreaterThan(0);
      expect(recipe.rarity).toBeTruthy();
      expect(recipe.gearTrait).toBeTruthy();
    }
  });

  it('only uses valid solid/structural mana types', async () => {
    const { FABRICATOR_RECIPES } = await import('@/lib/game/data/fabricator-recipes');
    const validManaTypes = new Set(['earth', 'metal', 'crystal', 'sand']);
    for (const recipe of Object.values(FABRICATOR_RECIPES)) {
      expect(validManaTypes.has(recipe.manaType)).toBe(true);
    }
  });

  it('no fire, water, air, light, dark, death, stellar, or void gear recipes', async () => {
    const { FABRICATOR_RECIPES } = await import('@/lib/game/data/fabricator-recipes');
    const invalidTypes = new Set(['fire', 'water', 'air', 'light', 'dark', 'death', 'stellar', 'void']);
    for (const recipe of Object.values(FABRICATOR_RECIPES)) {
      expect(invalidTypes.has(recipe.manaType)).toBe(false);
    }
  });

  it('getRecipesByManaType filters correctly', async () => {
    const { getRecipesByManaType } = await import('@/lib/game/data/fabricator-recipes');
    const earthRecipes = getRecipesByManaType('earth');
    expect(earthRecipes.length).toBeGreaterThan(0);
    for (const r of earthRecipes) {
      expect(r.manaType).toBe('earth');
    }

    const empty = getRecipesByManaType('nonexistent');
    expect(empty).toEqual([]);
  });

  it('getRecipeById returns correct recipe', async () => {
    const { getRecipeById, FABRICATOR_RECIPES } = await import('@/lib/game/data/fabricator-recipes');
    const firstId = Object.values(FABRICATOR_RECIPES)[0].id;
    const recipe = getRecipeById(firstId);
    expect(recipe).toBeDefined();
    expect(recipe!.id).toBe(firstId);

    const missing = getRecipeById('nonexistent');
    expect(missing).toBeUndefined();
  });

  it('canCraftRecipe returns correct availability', async () => {
    const { canCraftRecipe, FABRICATOR_RECIPES } = await import('@/lib/game/data/fabricator-recipes');
    const recipe = Object.values(FABRICATOR_RECIPES)[0];

    // Empty materials => cannot craft
    const result1 = canCraftRecipe(recipe, {}, 0);
    expect(result1.canCraft).toBe(false);
    expect(Object.keys(result1.missingMaterials).length).toBeGreaterThan(0);
    expect(result1.missingMana).toBeGreaterThan(0);

    // Sufficient materials and mana => can craft
    const sufficientMats: Record<string, number> = {};
    for (const [matId, amount] of Object.entries(recipe.materials)) {
      sufficientMats[matId] = amount;
    }
    const result2 = canCraftRecipe(recipe, sufficientMats, recipe.manaCost);
    expect(result2.canCraft).toBe(true);
    expect(Object.keys(result2.missingMaterials)).toHaveLength(0);
    expect(result2.missingMana).toBe(0);
  });
});

// ─── Test: File size limits ────────────────────────────────────────────────────

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

  it('FabricatorSubTab.tsx is under 400 lines', async () => {
    const fs = await import('fs');
    const path = await import('path');
    const content = fs.readFileSync(
      path.join(__dirname, 'CraftingTab', 'FabricatorSubTab.tsx'),
      'utf-8',
    );
    const lines = content.split('\n').length;
    expect(lines).toBeLessThan(400);
  });

  it('EnchanterSubTab.tsx is under 400 lines', async () => {
    const fs = await import('fs');
    const path = await import('path');
    const content = fs.readFileSync(
      path.join(__dirname, 'CraftingTab', 'EnchanterSubTab.tsx'),
      'utf-8',
    );
    const lines = content.split('\n').length;
    expect(lines).toBeLessThan(400);
  });
});
