import { describe, it, expect } from 'vitest';
import {
  checkRecipeMaterials,
  deductRecipeMaterials,
  refundCraftMaterials,
} from '../crafting-utils';

function makeRecipe(materials = { manaCrystalDust: 5, earthShard: 2 }, manaCost = 100): any {
  return {
    id: 'test',
    equipmentTypeId: 'oakStaff',
    name: 'Test',
    description: '',
    rarity: 'common' as const,
    materials,
    manaCost,
    craftTime: 1,
    minFloor: 1,
    unlocked: true,
  };
}

describe('checkRecipeMaterials', () => {
  it('should return canCraft true when all materials present', () => {
    const result = checkRecipeMaterials(makeRecipe(), { manaCrystalDust: 5, earthShard: 2 });
    expect(result.canCraft).toBe(true);
    expect(result.missingMaterials).toEqual({});
  });

  it('should return canCraft false when missing materials', () => {
    const result = checkRecipeMaterials(makeRecipe(), { manaCrystalDust: 3 });
    expect(result.canCraft).toBe(false);
    expect(result.missingMaterials).toEqual({ manaCrystalDust: 2, earthShard: 2 });
  });

  it('should return canCraft false when materials are empty', () => {
    const result = checkRecipeMaterials(makeRecipe(), {} as any);
    expect(result.canCraft).toBe(false);
    expect(result.missingMaterials).toEqual({ manaCrystalDust: 5, earthShard: 2 });
  });

  it('should handle partial shortage', () => {
    const result = checkRecipeMaterials(makeRecipe(), { manaCrystalDust: 4, earthShard: 2 });
    expect(result.canCraft).toBe(false);
    expect(result.missingMaterials).toEqual({ manaCrystalDust: 1 });
  });

  it('should handle excess materials', () => {
    const result = checkRecipeMaterials(makeRecipe(), { manaCrystalDust: 10, earthShard: 5 });
    expect(result.canCraft).toBe(true);
    expect(result.missingMaterials).toEqual({});
  });

  it('should handle recipe with no materials', () => {
    const emptyRecipe = makeRecipe({} as any);
    const result = checkRecipeMaterials(emptyRecipe, {} as any);
    expect(result.canCraft).toBe(true);
    expect(result.missingMaterials).toEqual({});
  });
});

describe('deductRecipeMaterials', () => {
  it('should deduct materials correctly', () => {
    const result = deductRecipeMaterials(makeRecipe(), { manaCrystalDust: 10, earthShard: 5 });
    expect(result.manaCrystalDust).toBe(5);
    expect(result.earthShard).toBe(3);
  });

  it('should remove materials that reach zero', () => {
    const result = deductRecipeMaterials(makeRecipe(), { manaCrystalDust: 5, earthShard: 2 });
    expect(result.manaCrystalDust).toBeUndefined();
    expect(result.earthShard).toBeUndefined();
  });

  it('should not go below zero', () => {
    const result = deductRecipeMaterials(makeRecipe(), { manaCrystalDust: 3, earthShard: 1 });
    // 3 - 5 = -2 → removed, 1 - 2 = -1 → removed
    expect(result.manaCrystalDust).toBeUndefined();
    expect(result.earthShard).toBeUndefined();
  });

  it('should preserve other materials', () => {
    const result = deductRecipeMaterials(makeRecipe(), {
      manaCrystalDust: 10,
      earthShard: 5,
      elementalCore: 3,
    });
    expect(result.elementalCore).toBe(3);
  });

  it('should handle empty materials', () => {
    const result = deductRecipeMaterials(makeRecipe(), {} as any);
    expect(result).toEqual({});
  });
});

describe('refundCraftMaterials', () => {
  it('should refund at default 50% rate', () => {
    // Default recipe: { manaCrystalDust: 5, earthShard: 2 }
    // 50% of 5 = 2.5 → floor = 2
    // 50% of 2 = 1 → floor = 1
    const result = refundCraftMaterials(makeRecipe());
    expect(result.manaCrystalDust).toBe(2);
    expect(result.earthShard).toBe(1);
  });

  it('should refund at custom rate', () => {
    // 75% of 5 = 3.75 → floor = 3
    // 75% of 2 = 1.5 → floor = 1
    const result = refundCraftMaterials(makeRecipe(), 0.75);
    expect(result.manaCrystalDust).toBe(3);
    expect(result.earthShard).toBe(1);
  });

  it('should refund zero at 0% rate', () => {
    const result = refundCraftMaterials(makeRecipe(), 0);
    expect(result.manaCrystalDust).toBe(0);
    expect(result.earthShard).toBe(0);
  });

  it('should refund full at 100% rate', () => {
    // 100% of 5 = 5
    // 100% of 2 = 2
    const result = refundCraftMaterials(makeRecipe(), 1);
    expect(result.manaCrystalDust).toBe(5);
    expect(result.earthShard).toBe(2);
  });

  it('should floor fractional refunds', () => {
    // Recipe with manaCrystalDust: 7
    // 50% of 7 = 3.5 → floor = 3
    const recipeWithOdd = makeRecipe({ manaCrystalDust: 7 } as any);
    const result = refundCraftMaterials(recipeWithOdd, 0.5);
    expect(result.manaCrystalDust).toBe(3);
  });

  it('should handle empty recipe materials', () => {
    const emptyRecipe = makeRecipe({} as any);
    const result = refundCraftMaterials(emptyRecipe);
    expect(result).toEqual({});
  });
});