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

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

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

function org(overrides: Partial<Org> = {}): Org {
  return {
    id: 1,
    orgNo: '001',
    orgName: '국제방송교류재단',
    status: 'ACTIVE',
    deptName: '데이터정보화팀',
    managerName: '송민지',
    managerTitle: '과장',
    managerPhone: '02-3475-5434',
    managerEmail: 'ming@arirang.com',
    channelIdMj: 'chan-mj',
    channelIdLaw: 'chan-law',
    ...overrides,
  }
}

beforeEach(() => {
  mocks.getPosts.mockReset().mockResolvedValue([])
  mocks.getFiles.mockReset().mockResolvedValue([])
  mocks.getMemos.mockReset().mockResolvedValue([])
})

describe('OrgOverview', () => {
  it('연번_기관명 헤더와 신청기관 담당자 정보를 보여준다', async () => {
    render(<OrgOverview org={org()} />)

    expect(screen.getByText('001_국제방송교류재단')).toBeTruthy()
    expect(screen.getByText('데이터정보화팀')).toBeTruthy()
    expect(screen.getByText('송민지 과장')).toBeTruthy()
    expect(screen.getByText('02-3475-5434')).toBeTruthy()
    expect(screen.getByText('ming@arirang.com')).toBeTruthy()
    await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled())
  })

  it('아직 연동 전인 문정원 담당자와 담당 변호사 카드는 자리만 보여준다', async () => {
    render(<OrgOverview org={org()} />)

    expect(screen.getByText('문정원 담당자')).toBeTruthy()
    expect(screen.getByText('담당 변호사')).toBeTruthy()
    expect(screen.getAllByText('추후 연동')).toHaveLength(2)
    await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled())
  })

  it('업무단계 12개가 순서대로 보인다', async () => {
    render(<OrgOverview org={org()} />)

    expect(screen.getByText('신청')).toBeTruthy()
    expect(screen.getByText('변호사 배당')).toBeTruthy()
    expect(screen.getByText('보고서 작성')).toBeTruthy()
    await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled())
  })

  it('기본 탭인 채팅은 자리표시 대신 채널 선택 화면을 보여준다', async () => {
    render(<OrgOverview org={org()} />)

    expect(screen.getByRole('button', { name: '문정원' })).toBeTruthy()
    await waitFor(() => expect(mocks.getPosts).toHaveBeenCalledWith(1, 'mj'))
  })

  it('탭을 누르면 해당 탭의 자리표시 내용으로 바뀐다', async () => {
    render(<OrgOverview org={org()} />)

    await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled())

    fireEvent.click(screen.getByRole('button', { name: '타임라인' }))

    expect(screen.getByText('타임라인 상세 화면은 추후 확정')).toBeTruthy()
    expect(screen.queryByRole('button', { name: '문정원' })).toBeNull()
  })

  it('자료 탭을 누르면 자료 목록 화면으로 바뀐다', async () => {
    render(<OrgOverview org={org()} />)

    fireEvent.click(screen.getByRole('button', { name: '자료' }))

    await waitFor(() => expect(mocks.getFiles).toHaveBeenCalledWith(1, 'mj'))
    expect(screen.getByRole('button', { name: '새로고침' })).toBeTruthy()
  })

  it('채널이 있으면 Mattermost 열기가 채널 링크로 활성화된다', async () => {
    render(<OrgOverview org={org()} />)

    const link = screen.getByRole('link', { name: 'Mattermost 열기' })
    expect(link).toHaveAttribute(
      'href',
      'https://hub.iten.co.kr/itn-hub/channels/org-001-mj',
    )
    await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled())
  })

  it('채널이 없으면 Mattermost 열기가 비활성이다', () => {
    render(<OrgOverview org={org({ channelIdMj: null, channelIdLaw: null, status: 'READY' })} />)

    expect(screen.queryByRole('link', { name: 'Mattermost 열기' })).toBeNull()
    expect(screen.getByRole('button', { name: 'Mattermost 열기' })).toBeDisabled()
  })

  it('치안정책연구소는 policy 채널 링크를 쓴다', async () => {
    render(
      <OrgOverview
        org={org({ orgNo: '008', orgName: '경찰청_치안정책연구소', channelIdMj: 'x' })}
      />,
    )

    expect(screen.getByRole('link', { name: 'Mattermost 열기' })).toHaveAttribute(
      'href',
      'https://hub.iten.co.kr/itn-hub/channels/org-008-policy-mj',
    )
    await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled())
  })

  it('미구현 동작 버튼들은 비활성이다', async () => {
    render(<OrgOverview org={org()} />)

    expect(screen.getByRole('button', { name: '진행단계 변경' })).toBeDisabled()
    expect(screen.getByRole('button', { name: '보고서 관리' })).toBeDisabled()
    await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled())
  })
})
