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

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

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

function org(overrides: Partial<Org> = {}): Org {
  return {
    id: 1,
    orgNo: '001',
    orgName: '국제방송교류재단',
    status: 'INFO_PENDING',
    deptName: null,
    managerName: null,
    managerTitle: null,
    managerPhone: null,
    managerEmail: null,
    channelIdMj: null,
    channelIdLaw: null,
    ...overrides,
  }
}

beforeEach(() => {
  mocks.updateContact.mockReset()
  mocks.provisionChannels.mockReset()
})

describe('OrgDetail', () => {
  it('정보 대기 상태면 채널 생성 버튼이 비활성이다', () => {
    render(<OrgDetail org={org()} onChanged={() => {}} />)

    expect(screen.getByRole('button', { name: '채널 생성' })).toBeDisabled()
  })

  it('생성 가능 상태면 채널 생성 버튼이 활성이다', () => {
    render(<OrgDetail org={org({ status: 'READY' })} onChanged={() => {}} />)

    expect(screen.getByRole('button', { name: '채널 생성' })).toBeEnabled()
  })

  it('담당자 정보를 저장하면 API를 호출한다', async () => {
    mocks.updateContact.mockResolvedValue(org({ status: 'READY' }))
    const onChanged = vi.fn()

    render(<OrgDetail org={org()} onChanged={onChanged} />)

    fireEvent.change(screen.getByLabelText('부서명'), { target: { value: '데이터정보화팀' } })
    fireEvent.change(screen.getByLabelText('담당자명'), { target: { value: '송민지' } })
    fireEvent.change(screen.getByLabelText('직급/직함'), { target: { value: '과장' } })
    fireEvent.change(screen.getByLabelText('연락처'), { target: { value: '02-3475-5434' } })
    fireEvent.change(screen.getByLabelText('이메일'), { target: { value: 'ming@arirang.com' } })
    fireEvent.click(screen.getByRole('button', { name: '정보 저장' }))

    await waitFor(() => {
      expect(mocks.updateContact).toHaveBeenCalledWith(1, {
        deptName: '데이터정보화팀',
        managerName: '송민지',
        managerTitle: '과장',
        managerPhone: '02-3475-5434',
        managerEmail: 'ming@arirang.com',
      })
      expect(onChanged).toHaveBeenCalled()
    })
  })

  it('채널 생성은 확인 다이얼로그에 만들어질 채널 2개를 보여준다', () => {
    render(<OrgDetail org={org({ status: 'READY' })} onChanged={() => {}} />)

    fireEvent.click(screen.getByRole('button', { name: '채널 생성' }))

    expect(screen.getByText('001_국제방송교류재단 (문정원)')).toBeTruthy()
    expect(screen.getByText('001_국제방송교류재단 (법률검토)')).toBeTruthy()
    expect(mocks.provisionChannels).not.toHaveBeenCalled()
  })

  it('확인을 눌러야 채널 생성 API가 호출된다', async () => {
    mocks.provisionChannels.mockResolvedValue({ mj: 'CREATED', law: 'CREATED', message: '' })

    render(<OrgDetail org={org({ status: 'READY' })} onChanged={() => {}} />)

    fireEvent.click(screen.getByRole('button', { name: '채널 생성' }))
    fireEvent.click(screen.getByRole('button', { name: '생성' }))

    await waitFor(() => expect(mocks.provisionChannels).toHaveBeenCalledWith(1))
  })

  it('부분 실패하면 재시도 안내를 보여준다', async () => {
    mocks.provisionChannels.mockResolvedValue({
      mj: 'CREATED',
      law: 'FAILED',
      message: '[법률검토] 서버 오류',
    })

    render(<OrgDetail org={org({ status: 'READY' })} onChanged={() => {}} />)

    fireEvent.click(screen.getByRole('button', { name: '채널 생성' }))
    fireEvent.click(screen.getByRole('button', { name: '생성' }))

    await waitFor(() => {
      expect(screen.getByText(/법률검토 채널 생성에 실패/)).toBeTruthy()
      expect(screen.getByText(/다시 눌러도 안전/)).toBeTruthy()
    })
  })
})
