import { describe, it, expect, vi, beforeEach } from 'vitest'
import { shallowMount } from '@vue/test-utils'
import LiteraturePreviewDrawer from '../LiteraturePreviewDrawer.vue'

const mockLitData = {
  pmid: 12345,
  title: 'Phase III Trial of Pembrolizumab',
  authors: [{ family: 'Smith', given: 'J' }],
  journal: 'NEJM',
  pub_date: '2024-06-01',
  doi: '10.1056/NEJMoa2400001',
  abstract: 'This study evaluated pembrolizumab efficacy.',
}

interface DrawerVM {
  lit: unknown
  loading: boolean
  copyPmid: () => void
  copyDoi: () => void
}

function vm(wrapper: ReturnType<typeof shallowMount>): DrawerVM {
  return wrapper.vm as unknown as DrawerVM
}

vi.mock('../../../api/client', () => ({
  api: { get: vi.fn() },
}))

describe('LiteraturePreviewDrawer', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('does not fetch when mounted with show=false', async () => {
    const { api } = await import('../../../api/client')
    shallowMount(LiteraturePreviewDrawer, {
      props: { show: false, pmid: 12345 },
    })
    expect(api.get).not.toHaveBeenCalled()
  })

  it('fetches data when show becomes true and stores it internally', async () => {
    const { api } = await import('../../../api/client')
    vi.mocked(api.get).mockResolvedValue({ data: mockLitData })

    const wrapper = shallowMount(LiteraturePreviewDrawer, {
      props: { show: false, pmid: 12345 },
    })

    expect(vm(wrapper).lit).toBeNull()

    await wrapper.setProps({ show: true })
    await new Promise(r => setTimeout(r, 0))

    expect(api.get).toHaveBeenCalledWith('/public/literature/12345')
    expect(vm(wrapper).lit).toEqual(mockLitData)
    expect(vm(wrapper).loading).toBe(false)
  })

  it('handles API error gracefully', async () => {
    const { api } = await import('../../../api/client')
    vi.mocked(api.get).mockRejectedValue(new Error('Network error'))

    const wrapper = shallowMount(LiteraturePreviewDrawer, {
      props: { show: true, pmid: 12345 },
    })
    await new Promise(r => setTimeout(r, 0))

    expect(vm(wrapper).lit).toBeNull()
    expect(vm(wrapper).loading).toBe(false)
  })

  it('resets lit when show becomes false', async () => {
    const { api } = await import('../../../api/client')
    vi.mocked(api.get).mockResolvedValue({ data: mockLitData })

    const wrapper = shallowMount(LiteraturePreviewDrawer, {
      props: { show: false, pmid: 12345 },
    })
    await wrapper.setProps({ show: true })
    await new Promise(r => setTimeout(r, 0))
    expect(vm(wrapper).lit).toEqual(mockLitData)

    await wrapper.setProps({ show: false })
    expect(vm(wrapper).lit).toBeNull()
  })

  it('watcher resets lit on show=false', async () => {
    const wrapper = shallowMount(LiteraturePreviewDrawer, {
      props: { show: true, pmid: 12345 },
    })

    await wrapper.setProps({ show: false })
    expect(vm(wrapper).lit).toBeNull()
  })

  it('exposes copyPmid and copyDoi functions', () => {
    const wrapper = shallowMount(LiteraturePreviewDrawer, {
      props: { show: true, pmid: 12345 },
    })

    vm(wrapper).lit = mockLitData
    expect(typeof vm(wrapper).copyPmid).toBe('function')
    expect(typeof vm(wrapper).copyDoi).toBe('function')
  })
})
