import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { MemoryRouter } from 'react-router-dom'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'

import QuestionBankPage from './QuestionBankPage'
import api from '../api/client'

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

vi.mock('../context/AuthContext', () => ({
  useAuth: () => ({ user: { role: 'admin' } }),
}))

function mockInitialRequests() {
  api.get.mockImplementation((url) => {
    if (url === '/question-categories/') return Promise.resolve({ data: [] })
    if (url === '/favorites') return Promise.resolve({ data: [] })
    if (url === '/tags') return Promise.resolve({ data: { subjects: [], diseases: [], keywords: [] } })
    if (url === '/questions/bank') return Promise.resolve({ data: { questions: [], total: 0 } })
    return Promise.resolve({ data: [] })
  })
}

function renderPage() {
  return render(
    <MemoryRouter>
      <QuestionBankPage />
    </MemoryRouter>
  )
}

describe('QuestionBankPage QTI actions', () => {
  let originalCreateElement
  let fileInput

  beforeEach(() => {
    vi.clearAllMocks()
    mockInitialRequests()
    originalCreateElement = document.createElement.bind(document)
    fileInput = null

    vi.spyOn(document, 'createElement').mockImplementation((tagName, options) => {
      const element = originalCreateElement(tagName, options)
      if (tagName === 'input') {
        fileInput = element
        vi.spyOn(element, 'click').mockImplementation(() => {})
      }
      return element
    })
  })

  afterEach(() => {
    document.createElement.mockRestore()
  })

  it('imports QTI files with an in-app success dialog', async () => {
    api.post.mockResolvedValueOnce({ data: { imported: 3, total_items: 4, errors: ['Skipped duplicate'] } })

    renderPage()
    await userEvent.click(await screen.findByRole('button', { name: 'Import QTI' }))

    expect(fileInput).toBeTruthy()
    expect(fileInput.accept).toBe('.xml')

    const file = new File(['<questestinterop />'], 'questions.xml', { type: 'text/xml' })
    Object.defineProperty(fileInput, 'files', { value: [file], configurable: true })
    fireEvent.change(fileInput)

    await waitFor(() => {
      expect(api.post).toHaveBeenCalledWith('/questions/import/qti', expect.any(FormData))
    })
    expect(await screen.findByText('QTI Import Complete')).toBeInTheDocument()
    expect(screen.getByText('Imported 3 of 4 questions. 1 error(s).')).toBeInTheDocument()
  })

  it('shows QTI export failures instead of swallowing them', async () => {
    api.get.mockImplementation((url) => {
      if (url.startsWith('/questions/export/qti')) {
        return Promise.reject({ response: { data: { detail: 'Export unavailable' } } })
      }
      if (url === '/question-categories/') return Promise.resolve({ data: [] })
      if (url === '/favorites') return Promise.resolve({ data: [] })
      if (url === '/tags') return Promise.resolve({ data: { subjects: [], diseases: [], keywords: [] } })
      if (url === '/questions/bank') return Promise.resolve({ data: { questions: [], total: 0 } })
      return Promise.resolve({ data: [] })
    })

    renderPage()
    await userEvent.click(await screen.findByRole('button', { name: 'Export QTI' }))

    expect(await screen.findByText('Export Failed')).toBeInTheDocument()
    expect(screen.getByText('Export unavailable')).toBeInTheDocument()
  })
})
