import { MemoryRouter } from 'react-router-dom'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { beforeEach, describe, expect, it, vi } from 'vitest'

import { AuthContext, type AuthContextValue } from '@/app/providers/auth-context'
import type { AuthCapabilities, TokenBundle } from '@/types'
import { BootstrapAdminPage } from './BootstrapAdminPage'

const getAuthCapabilitiesMock = vi.fn<() => Promise<AuthCapabilities>>()
const bootstrapAdminMock = vi.fn<(payload: unknown, bootstrapSecret: string) => Promise<TokenBundle>>()
const onLoginSuccessMock = vi.fn<(tokenBundle: TokenBundle) => Promise<void>>()

vi.mock('@/services/auth', () => ({
  getAuthCapabilities: () => getAuthCapabilitiesMock(),
  bootstrapAdmin: (payload: unknown, bootstrapSecret: string) => bootstrapAdminMock(payload, bootstrapSecret),
}))

const authContextValue: AuthContextValue = {
  user: null,
  roles: [],
  isAdmin: false,
  isAuthenticated: false,
  isLoading: false,
  onLoginSuccess: (tokenBundle) => onLoginSuccessMock(tokenBundle),
  logout: vi.fn(async () => {}),
  refreshUser: vi.fn(async () => {}),
}

function renderBootstrapAdminPage() {
  return render(
    <MemoryRouter initialEntries={['/bootstrap-admin']}>
      <AuthContext.Provider value={authContextValue}>
        <BootstrapAdminPage />
      </AuthContext.Provider>
    </MemoryRouter>,
  )
}

describe('BootstrapAdminPage', () => {
  beforeEach(() => {
    getAuthCapabilitiesMock.mockReset()
    bootstrapAdminMock.mockReset()
    onLoginSuccessMock.mockReset()

    getAuthCapabilitiesMock.mockResolvedValue({
      password: true,
      email_activation: false,
      email_code: false,
      sms_code: false,
      password_reset: false,
      admin_bootstrap_required: true,
      oauth_providers: [],
    })
    bootstrapAdminMock.mockResolvedValue({
      access_token: 'access-token',
      refresh_token: 'refresh-token',
      expires_in: 7200,
      user: {
        id: 1,
        username: 'bootstrap_admin',
        email: 'bootstrap_admin@example.com',
        phone: '',
        nickname: 'Bootstrap Admin',
        avatar: '',
        status: 1,
      },
    })
    onLoginSuccessMock.mockResolvedValue(undefined)
  })

  it('renders the first-admin bootstrap form when the system has no active admin', async () => {
    renderBootstrapAdminPage()

    await waitFor(() => expect(getAuthCapabilitiesMock).toHaveBeenCalledTimes(1))

    expect(screen.getByRole('heading', { name: '初始化首个管理员账号' })).toBeInTheDocument()
    expect(screen.getByPlaceholderText('管理员用户名')).toBeInTheDocument()
    expect(screen.getByPlaceholderText('引导密钥')).toBeInTheDocument()
    expect(screen.getByPlaceholderText('管理员密码')).toBeInTheDocument()
    expect(screen.getByRole('button', { name: '完成初始化并进入系统' })).toBeInTheDocument()
  })

  it('submits the bootstrap request and hands the created session to the auth provider', async () => {
    const user = userEvent.setup()
    renderBootstrapAdminPage()

    await waitFor(() => expect(screen.getByPlaceholderText('管理员用户名')).toBeInTheDocument())

    await user.type(screen.getByPlaceholderText('管理员用户名'), 'bootstrap_admin')
    await user.type(screen.getByPlaceholderText('管理员昵称（选填）'), 'Bootstrap Admin')
    await user.type(screen.getByPlaceholderText('管理员邮箱（选填）'), 'bootstrap_admin@example.com')
    await user.type(screen.getByPlaceholderText('引导密钥'), 'bootstrap-secret')
    await user.type(screen.getByPlaceholderText('管理员密码'), 'Bootstrap123!@#')
    await user.type(screen.getByPlaceholderText('确认管理员密码'), 'Bootstrap123!@#')
    await user.click(screen.getByRole('button', { name: '完成初始化并进入系统' }))

    await waitFor(() =>
      expect(bootstrapAdminMock).toHaveBeenCalledWith(
        {
          username: 'bootstrap_admin',
          nickname: 'Bootstrap Admin',
          email: 'bootstrap_admin@example.com',
          password: 'Bootstrap123!@#',
        },
        'bootstrap-secret',
      ),
    )

    await waitFor(() =>
      expect(onLoginSuccessMock).toHaveBeenCalledWith(expect.objectContaining({
        access_token: 'access-token',
        refresh_token: 'refresh-token',
      })),
    )
  })

  it('shows an informational state when admin bootstrap is already closed', async () => {
    getAuthCapabilitiesMock.mockResolvedValue({
      password: true,
      email_activation: false,
      email_code: false,
      sms_code: false,
      password_reset: false,
      admin_bootstrap_required: false,
      oauth_providers: [],
    })

    renderBootstrapAdminPage()

    expect(await screen.findByText('管理员已完成初始化')).toBeInTheDocument()
    expect(screen.getByRole('link', { name: '返回登录' })).toBeInTheDocument()
  })
})
