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

const downloadMock = vi.fn()
const postMock = vi.fn()

vi.mock('@/lib/http/client', () => ({
  download: downloadMock,
  post: postMock,
}))

describe('import-export service', () => {
  beforeEach(() => {
    downloadMock.mockReset()
    postMock.mockReset()
  })

  it('exports users with specified format and fields', async () => {
    const blob = new Blob(['csv,data'], { type: 'text/csv' })
    downloadMock.mockResolvedValue(blob)

    const clickMock = vi.spyOn(HTMLAnchorElement.prototype, 'click').mockImplementation(() => undefined)
    const createObjectURLMock = vi.fn(() => 'blob:mock')
    const revokeObjectURLMock = vi.fn()

    Object.defineProperty(window.URL, 'createObjectURL', {
      configurable: true,
      value: createObjectURLMock,
    })
    Object.defineProperty(window.URL, 'revokeObjectURL', {
      configurable: true,
      value: revokeObjectURLMock,
    })

    const { exportUsers } = await import('./import-export')
    await exportUsers({
      format: 'csv',
      fields: ['id', 'username', 'email'],
      keyword: 'alice',
      status: 1,
    })

    expect(downloadMock).toHaveBeenCalledWith('/admin/users/export', {
      format: 'csv',
      fields: 'id,username,email',
      keyword: 'alice',
      status: 1,
    })

    expect(createObjectURLMock).toHaveBeenCalled()
    expect(clickMock).toHaveBeenCalled()
    expect(revokeObjectURLMock).toHaveBeenCalled()
  })

  it('downloads import template', async () => {
    const blob = new Blob(['template,data'], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
    downloadMock.mockResolvedValue(blob)

    const clickMock = vi.spyOn(HTMLAnchorElement.prototype, 'click').mockImplementation(() => undefined)
    const createObjectURLMock = vi.fn(() => 'blob:mock')
    const revokeObjectURLMock = vi.fn()

    Object.defineProperty(window.URL, 'createObjectURL', {
      configurable: true,
      value: createObjectURLMock,
    })
    Object.defineProperty(window.URL, 'revokeObjectURL', {
      configurable: true,
      value: revokeObjectURLMock,
    })

    const { downloadImportTemplate } = await import('./import-export')
    await downloadImportTemplate('xlsx')

    expect(downloadMock).toHaveBeenCalledWith('/admin/users/import/template', { format: 'xlsx' })

    expect(createObjectURLMock).toHaveBeenCalled()
    expect(clickMock).toHaveBeenCalled()
    expect(revokeObjectURLMock).toHaveBeenCalled()
  })

  it('imports users from csv file', async () => {
    const file = new File(['username,email'], 'users.csv', { type: 'text/csv' })
    const importResult = {
      success_count: 10,
      fail_count: 2,
      errors: ['Row 3: Invalid email', 'Row 7: Missing username'],
      message: 'Import completed with errors',
    }
    postMock.mockResolvedValue(importResult)

    const { importUsers } = await import('./import-export')
    const result = await importUsers(file)

    expect(postMock).toHaveBeenCalledWith('/admin/users/import', expect.any(FormData))
    const payload = postMock.mock.calls[0][1] as FormData
    expect(payload.get('file')).toBe(file)
    expect(result).toEqual(importResult)
  })

  it('imports users from xlsx file', async () => {
    const file = new File(['xlsx,data'], 'users.xlsx', {
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    })
    const importResult = {
      success_count: 50,
      fail_count: 0,
      errors: [],
      message: 'Import successful',
    }
    postMock.mockResolvedValue(importResult)

    const { importUsers } = await import('./import-export')
    const result = await importUsers(file)

    expect(postMock).toHaveBeenCalledWith('/admin/users/import', expect.any(FormData))
    const payload = postMock.mock.calls[0][1] as FormData
    expect(payload.get('file')).toBe(file)
    expect(result).toEqual(importResult)
  })
})
