import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import ChannelFiles from './ChannelFiles'
import type { FileView, Org } from '../api/client'

const mocks = vi.hoisted(() => ({
  getFiles: vi.fn(),
}))

vi.mock('../api/client', async (importOriginal) => ({
  ...(await importOriginal<typeof import('../api/client')>()),
  getFiles: mocks.getFiles,
}))

function org(overrides: Partial<Org> = {}): Org {
  return {
    id: 1,
    orgNo: '001',
    orgName: '국제방송교류재단',
    status: 'ACTIVE',
    applicant: null,
    mj: null,
    lawyer: null,
    lawyerAssignedDate: null,
    channelIdMj: 'chan-mj',
    channelIdLaw: 'chan-law',
    ...overrides,
  }
}

function file(overrides: Partial<FileView> = {}): FileView {
  return {
    id: 'f1',
    name: '보고서.pdf',
    size: 1234,
    mimeType: 'application/pdf',
    createAt: new Date('2026-07-01T10:30:00').getTime(),
    uploader: '송민지',
    ...overrides,
  }
}

beforeEach(() => {
  mocks.getFiles.mockReset()
})

describe('ChannelFiles', () => {
  it('목록을 표로 보여준다', async () => {
    mocks.getFiles.mockResolvedValue([file()])

    render(<ChannelFiles org={org()} />)

    await waitFor(() => {
      expect(screen.getByText('보고서.pdf')).toBeTruthy()
      expect(screen.getByText('송민지')).toBeTruthy()
    })
    expect(screen.getByText('보고서.pdf').closest('a')).toHaveAttribute('href', '/api/files/f1')
  })

  it('새로고침을 누르면 다시 조회한다', async () => {
    mocks.getFiles.mockResolvedValue([])

    render(<ChannelFiles org={org()} />)

    await waitFor(() => expect(mocks.getFiles).toHaveBeenCalledTimes(1))

    fireEvent.click(screen.getByRole('button', { name: '새로고침' }))

    await waitFor(() => expect(mocks.getFiles).toHaveBeenCalledTimes(2))
  })

  it('자료가 없으면 안내 문구를 보여준다', async () => {
    mocks.getFiles.mockResolvedValue([])

    render(<ChannelFiles org={org()} />)

    await waitFor(() => {
      expect(screen.getByText('등록된 자료가 없습니다.')).toBeTruthy()
    })
  })

  it('조회 중에는 불러오는 중 문구를 보여준다', () => {
    mocks.getFiles.mockReturnValue(new Promise(() => {}))

    render(<ChannelFiles org={org()} />)

    expect(screen.getByText('불러오는 중…')).toBeTruthy()
  })

  it('양쪽 채널이 모두 없으면 안내 문구를 보여주고 API를 호출하지 않는다', () => {
    render(<ChannelFiles org={org({ channelIdMj: null, channelIdLaw: null })} />)

    expect(screen.getByText('채널이 아직 생성되지 않았습니다.')).toBeTruthy()
    expect(mocks.getFiles).not.toHaveBeenCalled()
  })
})
