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

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

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

function contact(overrides: Partial<Contact> = {}): Contact {
  return {
    id: 1,
    category: 'APPLICANT',
    name: '송민지',
    affiliation: '국제방송교류재단',
    deptName: '데이터정보화팀',
    title: '과장',
    phone: '02-3475-5434',
    email: 'ming@arirang.com',
    ...overrides,
  }
}

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

describe('ContactPickerModal', () => {
  it('카테고리로 담당자 목록을 불러와 행으로 보여준다', async () => {
    mocks.getContacts.mockResolvedValue([contact()])

    render(
      <ContactPickerModal
        category="APPLICANT"
        title="신청기관 담당자 선택"
        onSelect={() => {}}
        onClose={() => {}}
      />,
    )

    expect(mocks.getContacts).toHaveBeenCalledWith('APPLICANT')
    await waitFor(() => expect(screen.getByText('송민지')).toBeTruthy())
    expect(screen.getByText(/국제방송교류재단/)).toBeTruthy()
    expect(screen.getByText(/데이터정보화팀/)).toBeTruthy()
    expect(screen.getByRole('button', { name: '선택' })).toBeTruthy()
  })

  it('담당자가 없으면 안내 문구와 하단 메모를 보여준다', async () => {
    mocks.getContacts.mockResolvedValue([])

    render(
      <ContactPickerModal category="MJ" title="문정원 담당자 선택" onSelect={() => {}} onClose={() => {}} />,
    )

    await waitFor(() => {
      expect(screen.getByText('등록된 담당자가 없습니다.')).toBeTruthy()
    })
    expect(screen.getByText('담당자 등록·수정은 담당자관리 메뉴에서 합니다.')).toBeTruthy()
  })

  it('검색어로 이름·소속을 걸러낸다', async () => {
    mocks.getContacts.mockResolvedValue([
      contact({ id: 1, name: '송민지', affiliation: '국제방송교류재단' }),
      contact({ id: 2, name: '권유나', affiliation: '세종학당재단' }),
    ])

    render(
      <ContactPickerModal category="APPLICANT" title="신청기관 담당자 선택" onSelect={() => {}} onClose={() => {}} />,
    )

    await waitFor(() => expect(screen.getByText('송민지')).toBeTruthy())

    fireEvent.change(screen.getByLabelText('담당자 검색'), { target: { value: '세종' } })

    expect(screen.queryByText('송민지')).toBeNull()
    expect(screen.getByText('권유나')).toBeTruthy()
  })

  it('선택 버튼을 누르면 onSelect가 그 담당자로 호출된다', async () => {
    const target = contact({ id: 42, name: '송민지' })
    mocks.getContacts.mockResolvedValue([target])
    const onSelect = vi.fn()

    render(
      <ContactPickerModal category="APPLICANT" title="신청기관 담당자 선택" onSelect={onSelect} onClose={() => {}} />,
    )

    await waitFor(() => expect(screen.getByText('송민지')).toBeTruthy())
    fireEvent.click(screen.getByRole('button', { name: '선택' }))

    expect(onSelect).toHaveBeenCalledWith(target)
  })

  it('닫기 버튼을 누르면 onClose가 호출된다', async () => {
    mocks.getContacts.mockResolvedValue([])
    const onClose = vi.fn()

    render(
      <ContactPickerModal category="APPLICANT" title="신청기관 담당자 선택" onSelect={() => {}} onClose={onClose} />,
    )

    fireEvent.click(screen.getByRole('button', { name: '닫기' }))

    expect(onClose).toHaveBeenCalled()
  })

  it('Esc를 누르면 onClose가 호출된다', async () => {
    mocks.getContacts.mockResolvedValue([])
    const onClose = vi.fn()

    render(
      <ContactPickerModal category="APPLICANT" title="신청기관 담당자 선택" onSelect={() => {}} onClose={onClose} />,
    )

    fireEvent.keyDown(window, { key: 'Escape' })

    expect(onClose).toHaveBeenCalled()
  })
})
