import { describe, it, expect } from 'vitest';
import {
  calculatePrepTime,
  calculateApplicationTime,
  calculatePrepManaCost,
  calculateApplicationManaPerHour,
  calculateManaPerHourForPrep,
} from '../crafting-utils';

function makeDesign(overrides = {}): any {
  return {
    id: 'design_1',
    name: 'Test Design',
    effects: [{ effectId: 'fireDamage', stacks: 2 }],
    totalCapacityUsed: 20,
    ...overrides,
  };
}

describe('calculatePrepTime', () => {
  it('should return base 2 for zero capacity', () => {
    expect(calculatePrepTime(0)).toBe(2);
  });

  it('should return 2 for capacity less than 50', () => {
    expect(calculatePrepTime(49)).toBe(2);
  });

  it('should add 1 hour per 50 capacity', () => {
    expect(calculatePrepTime(50)).toBe(3);
    expect(calculatePrepTime(100)).toBe(4);
    expect(calculatePrepTime(150)).toBe(5);
  });

  it('should floor capacity division', () => {
    expect(calculatePrepTime(99)).toBe(3); // floor(99/50) = 1 → 2+1=3
    expect(calculatePrepTime(101)).toBe(4); // floor(101/50) = 2 → 2+2=4
  });
});

describe('calculateApplicationTime', () => {
  it('should return base 2 for design with no effects', () => {
    const design = makeDesign({ effects: [] });
    expect(calculateApplicationTime(design)).toBe(2);
  });

  it('should add stacks to base time', () => {
    const design = makeDesign({ effects: [{ effectId: 'fireDamage', stacks: 3 }] });
    expect(calculateApplicationTime(design)).toBe(5);
  });

  it('should sum stacks from multiple effects', () => {
    const design = makeDesign({
      effects: [
        { effectId: 'fireDamage', stacks: 2 },
        { effectId: 'waterShield', stacks: 3 },
      ],
    });
    expect(calculateApplicationTime(design)).toBe(7);
  });

  it('should handle single-stack design', () => {
    const design = makeDesign({ effects: [{ effectId: 'fireDamage', stacks: 1 }] });
    expect(calculateApplicationTime(design)).toBe(3);
  });
});

describe('calculatePrepManaCost', () => {
  it('should return 0 for zero capacity', () => {
    expect(calculatePrepManaCost(0)).toBe(0);
  });

  it('should multiply capacity by 10', () => {
    expect(calculatePrepManaCost(50)).toBe(500);
    expect(calculatePrepManaCost(100)).toBe(1000);
  });

  it('should handle fractional capacity', () => {
    expect(calculatePrepManaCost(25)).toBe(250);
  });
});

describe('calculateApplicationManaPerHour', () => {
  it('should return base 20 for design with no effects', () => {
    const design = makeDesign({ effects: [] });
    expect(calculateApplicationManaPerHour(design)).toBe(20);
  });

  it('should add 5 per stack', () => {
    const design = makeDesign({ effects: [{ effectId: 'fireDamage', stacks: 4 }] });
    expect(calculateApplicationManaPerHour(design)).toBe(40);
  });

  it('should sum stacks from multiple effects', () => {
    const design = makeDesign({
      effects: [
        { effectId: 'fireDamage', stacks: 1 },
        { effectId: 'waterShield', stacks: 2 },
      ],
    });
    expect(calculateApplicationManaPerHour(design)).toBe(35);
  });
});

describe('calculateManaPerHourForPrep', () => {
  it('should divide total prep cost by prep time', () => {
    // capacity=100 → prepManaCost=1000, prepTime=4 → 250/hr
    const prepTime = calculatePrepTime(100);
    expect(calculateManaPerHourForPrep(100, prepTime)).toBe(250);
  });

  it('should handle zero capacity', () => {
    const prepTime = calculatePrepTime(0);
    expect(calculateManaPerHourForPrep(0, prepTime)).toBe(0);
  });

  it('should handle fractional results', () => {
    // capacity=50 → prepManaCost=500, prepTime=3 → 166.666...
    const prepTime = calculatePrepTime(50);
    expect(calculateManaPerHourForPrep(50, prepTime)).toBeCloseTo(500 / 3, 5);
  });
});