import { describe, it, expect, beforeEach, vi } from 'vitest'
import { buildPngDownloadItem } from './png-item'

type ToBlobCb = (blob: Blob | null) => void
const mockToBlob = vi.fn((cb: ToBlobCb) => cb(new Blob(['png-bytes'])))

vi.mock('html2canvas', () => ({
  default: () => Promise.resolve({ toBlob: mockToBlob }),
}))

let revokeSpy: ReturnType<typeof vi.spyOn>

beforeEach(() => {
  mockToBlob.mockReset()
  mockToBlob.mockImplementation((cb: ToBlobCb) => cb(new Blob(['png-bytes'])))
  vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:png')
  revokeSpy = vi
    .spyOn(URL, 'revokeObjectURL')
    .mockImplementation(() => undefined)
})

describe('buildPngDownloadItem', () => {
  it('returns an item with the canonical PNG shape (id, label, icon)', () => {
    const item = buildPngDownloadItem({
      filename: 'demo',
      getCaptureEl: () => document.createElement('div'),
    })
    expect(item.id).toBe('png')
    expect(item.label).toBe('PNG')
    expect(item.icon).toBeTruthy()
  })

  it('honours a label override', () => {
    const item = buildPngDownloadItem({
      filename: 'demo',
      getCaptureEl: () => document.createElement('div'),
      label: 'Export image',
    })
    expect(item.label).toBe('Export image')
  })

  it('resolve() rasterises the capture element and returns a handle with .png filename', async () => {
    const item = buildPngDownloadItem({
      filename: 'sales',
      getCaptureEl: () => document.createElement('div'),
    })
    const handle = await item.resolve()
    expect(handle.url).toBe('blob:png')
    expect(handle.filename).toBe('sales.png')
    handle.revoke?.()
    expect(revokeSpy).toHaveBeenCalledWith('blob:png')
  })

  it('resolve() rejects when getCaptureEl returns null', async () => {
    const item = buildPngDownloadItem({
      filename: 'demo',
      getCaptureEl: () => null,
    })
    await expect(item.resolve()).rejects.toThrow(/No PNG capture element/)
  })

  it('forwards pixelRatio and backgroundColor overrides', async () => {
    const item = buildPngDownloadItem({
      filename: 'sales',
      getCaptureEl: () => document.createElement('div'),
      pixelRatio: 4,
      backgroundColor: '#fff',
    })
    const handle = await item.resolve()
    expect(handle.filename).toBe('sales.png')
  })
})
