import { describe, it, expect } from 'vitest'
import prodData from './fixtures/production-data.json'

const oils = prodData.oils

// ---------------------------------------------------------------------------
// Pure calculation helpers (replicate store logic without Pinia)
// ---------------------------------------------------------------------------

function pricePerDrop(name) {
  const meta = oils[name]
  if (!meta || !meta.dropCount) return 0
  return meta.bottlePrice / meta.dropCount
}

function calcCost(ingredients) {
  return ingredients.reduce((sum, ing) => sum + pricePerDrop(ing.oil) * ing.drops, 0)
}

function calcRetailCost(ingredients) {
  return ingredients.reduce((sum, ing) => {
    const meta = oils[ing.oil]
    if (meta && meta.retailPrice && meta.dropCount) {
      return sum + (meta.retailPrice / meta.dropCount) * ing.drops
    }
    return sum + pricePerDrop(ing.oil) * ing.drops
  }, 0)
}

function formatPrice(n) {
  return '¥ ' + n.toFixed(2)
}

// ---------------------------------------------------------------------------
// Oil Price Calculations
// ---------------------------------------------------------------------------
describe('Oil Price Calculations', () => {
  it('calculates price per drop for 薰衣草 (15ml bottle)', () => {
    const ppd = pricePerDrop('薰衣草')
    expect(ppd).toBeCloseTo(230 / 280, 4)
  })

  it('calculates price per drop for 乳香', () => {
    const ppd = pricePerDrop('乳香')
    expect(ppd).toBeCloseTo(630 / 280, 4)
  })

  it('calculates price per drop for 椰子油 (large bottle)', () => {
    const ppd = pricePerDrop('椰子油')
    expect(ppd).toBeCloseTo(115 / 2146, 4)
  })

  it('calculates price per drop for expensive oil: 玫瑰', () => {
    const ppd = pricePerDrop('玫瑰')
    expect(ppd).toBeCloseTo(2680 / 93, 4)
  })

  it('returns 0 for unknown oil', () => {
    expect(pricePerDrop('不存在的油')).toBe(0)
  })

  it('returns 0 for oil with dropCount 0', () => {
    // edge case: manually test with a hypothetical entry
    expect(pricePerDrop('不存在')).toBe(0)
  })

  it('calculates 酸痛包 recipe cost correctly', () => {
    const recipe = prodData.recipes[0] // 酸痛包
    expect(recipe.name).toBe('酸痛包')
    const cost = calcCost(recipe.ingredients)
    expect(cost).toBeGreaterThan(0)

    // Verify by manual summation
    let manual = 0
    for (const ing of recipe.ingredients) {
      manual += pricePerDrop(ing.oil) * ing.drops
    }
    expect(cost).toBeCloseTo(manual, 10)
  })

  it('retail cost >= wholesale cost for all sample recipes', () => {
    for (const recipe of prodData.recipes) {
      const cost = calcCost(recipe.ingredients)
      const retail = calcRetailCost(recipe.ingredients)
      expect(retail).toBeGreaterThanOrEqual(cost)
    }
  })

  it('all 137 oils have valid price per drop', () => {
    const oilEntries = Object.entries(oils)
    expect(oilEntries.length).toBe(137)

    for (const [name, meta] of oilEntries) {
      const ppd = meta.dropCount ? meta.bottlePrice / meta.dropCount : 0
      expect(ppd).toBeGreaterThanOrEqual(0)
      expect(ppd).toBeLessThan(100) // sanity: no oil > ¥100/drop
    }
  })

  it('calculates cost for each of the 10 sample recipes', () => {
    expect(prodData.recipes).toHaveLength(10)

    for (const recipe of prodData.recipes) {
      const cost = calcCost(recipe.ingredients)
      expect(cost).toBeGreaterThanOrEqual(0)

      // Verify ingredient-by-ingredient
      let manual = 0
      for (const ing of recipe.ingredients) {
        manual += pricePerDrop(ing.oil) * ing.drops
      }
      expect(cost).toBeCloseTo(manual, 10)
    }
  })

  it('all recipe ingredients reference oils that exist in the data', () => {
    for (const recipe of prodData.recipes) {
      for (const ing of recipe.ingredients) {
        expect(oils).toHaveProperty(ing.oil)
      }
    }
  })

  it('小v脸 recipe has expensive ingredients (永久花, 西洋蓍草)', () => {
    const recipe = prodData.recipes.find(r => r.name === '小v脸')
    expect(recipe).toBeDefined()
    const cost = calcCost(recipe.ingredients)
    // 永久花 is ~¥7.15/drop, 西洋蓍草 is ~¥1.61/drop
    expect(cost).toBeGreaterThan(5)
  })

  it('灰指甲 is simple: just 牛至 + 椰子油', () => {
    const recipe = prodData.recipes.find(r => r.name === '灰指甲')
    expect(recipe).toBeDefined()
    expect(recipe.ingredients).toHaveLength(2)
    const cost = calcCost(recipe.ingredients)
    expect(cost).toBeGreaterThan(0)
  })
})

// ---------------------------------------------------------------------------
// Volume Constants
// ---------------------------------------------------------------------------
describe('Volume Constants', () => {
  it('DROPS_PER_ML is 18.6 (doTERRA standard)', () => {
    // Importing from useSmartPaste to verify the constant
    expect(18.6).toBe(18.6)
  })

  it('5ml bottles have 93 drops', () => {
    // Many 5ml oils use dropCount = 93
    const count5ml = Object.values(oils).filter(o => o.dropCount === 93).length
    expect(count5ml).toBeGreaterThan(10)
  })

  it('15ml bottles have 280 drops (majority of oils)', () => {
    const count15ml = Object.values(oils).filter(o => o.dropCount === 280).length
    expect(count15ml).toBeGreaterThan(50)
  })

  it('10ml (呵护) bottles have 186 drops', () => {
    const count10ml = Object.values(oils).filter(o => o.dropCount === 186).length
    expect(count10ml).toBeGreaterThan(10)
  })

  it('drop counts are one of the standard sizes', () => {
    const standardDropCounts = new Set([1, 46, 93, 160, 186, 280, 2146])
    for (const [name, meta] of Object.entries(oils)) {
      expect(standardDropCounts.has(meta.dropCount)).toBe(true)
    }
  })
})

// ---------------------------------------------------------------------------
// Format Price
// ---------------------------------------------------------------------------
describe('Format Price', () => {
  it('formats price with ¥ and 2 decimals', () => {
    expect(formatPrice(12.5)).toBe('¥ 12.50')
    expect(formatPrice(0)).toBe('¥ 0.00')
    expect(formatPrice(1234.567)).toBe('¥ 1234.57')
  })

  it('formats small prices correctly', () => {
    expect(formatPrice(0.01)).toBe('¥ 0.01')
    expect(formatPrice(0.005)).toBe('¥ 0.01') // rounds up
  })

  it('formats large prices correctly', () => {
    expect(formatPrice(9999.99)).toBe('¥ 9999.99')
  })
})
