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

const lookupMock = vi.hoisted(() => ({
  resolveBuiltinPricing: vi.fn(),
}))

vi.mock('@/lib/model-pricing/lookup', () => ({
  resolveBuiltinPricing: lookupMock.resolveBuiltinPricing,
}))

import { calcImage, calcText, calcVideo, calcVoice } from '@/lib/billing/cost'

describe('billing/cost error branches', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('throws ambiguous pricing error when catalog has multiple candidates', () => {
    lookupMock.resolveBuiltinPricing.mockReturnValue({
      status: 'ambiguous_model',
      apiType: 'image',
      modelId: 'shared-model',
      candidates: [
        {
          apiType: 'image',
          provider: 'p1',
          modelId: 'shared-model',
          pricing: { mode: 'flat', flatAmount: 1 },
        },
        {
          apiType: 'image',
          provider: 'p2',
          modelId: 'shared-model',
          pricing: { mode: 'flat', flatAmount: 1 },
        },
      ],
    })

    expect(() => calcImage('shared-model', 1)).toThrow('Ambiguous image pricing modelId')
  })

  it('throws unknown model when catalog returns not_configured', () => {
    lookupMock.resolveBuiltinPricing.mockReturnValue({
      status: 'not_configured',
    })

    expect(() => calcImage('provider::missing-image-model', 1)).toThrow('Unknown image model pricing')
  })

  it('normalizes invalid numeric inputs to zero before pricing', () => {
    lookupMock.resolveBuiltinPricing.mockImplementation(
      (input: { selections?: { tokenType?: 'input' | 'output' } }) => {
        if (input.selections?.tokenType === 'input') return { status: 'resolved', amount: 2 }
        if (input.selections?.tokenType === 'output') return { status: 'resolved', amount: 4 }
        return { status: 'resolved', amount: 3 }
      },
    )

    expect(calcText('text-model', Number.NaN, 1_000_000)).toBeCloseTo(4, 8)
    expect(calcText('text-model', 1_000_000, Number.NaN)).toBeCloseTo(2, 8)
    expect(calcImage('image-model', Number.NaN)).toBe(0)
    expect(calcVideo('video-model', '720p', Number.NaN)).toBe(0)
    expect(calcVoice(Number.NaN)).toBe(0)
  })
})
