import { beforeEach, describe, expect, it, vi } from 'vitest'
import { render } from 'vitest-browser-react'
import { userEvent } from 'vitest/browser'
import { UserAuthForm } from './user-auth-form'

const navigate = vi.fn()
const setUserMock = vi.fn()
const setAccessTokenMock = vi.fn()
const postMock = vi.fn()

vi.mock('@/stores/auth-store', () => ({
  useAuthStore: () => ({
    auth: {
      setUser: setUserMock,
      setAccessToken: setAccessTokenMock,
    },
  }),
}))

vi.mock('@tanstack/react-router', async (importOriginal) => {
  const actual = await importOriginal<typeof import('@tanstack/react-router')>()
  return {
    ...actual,
    useNavigate: () => navigate,
  }
})

vi.mock('@/lib/api', () => ({
  api: {
    post: postMock,
  },
  getApiErrorMessage: (_error: unknown, fallback: string) => fallback,
}))

const loginResponse = {
  data: {
    code: 0,
    msg: 'success',
    data: {
      status: 'ok',
      token: 'server-token',
      user: {
        id: 'user-1',
        name: 'root',
        username: 'root',
        email: 'root@local.dev',
        role: 'super_admin',
        roleName: '超级管理员',
        mustChangePassword: 0,
        permissions: { '*': ['*'] },
      },
    },
  },
}

describe('UserAuthForm', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    postMock.mockResolvedValue(loginResponse)
  })

  it('渲染账号、密码和登录按钮', async () => {
    const screen = await render(<UserAuthForm />)

    await expect
      .element(screen.getByRole('textbox', { name: '账号' }))
      .toBeInTheDocument()
    await expect.element(screen.getByLabelText('密码')).toBeInTheDocument()
    await expect
      .element(screen.getByRole('button', { name: /登录/ }))
      .toBeInTheDocument()
  })

  it('登录成功后写入会话并跳转后台首页', async () => {
    const screen = await render(<UserAuthForm />)

    await userEvent.click(screen.getByRole('button', { name: /登录/ }))

    await vi.waitFor(() => expect(postMock).toHaveBeenCalledOnce())
    expect(postMock).toHaveBeenCalledWith('/api/user/login', {
      userName: 'root',
      password: '123456',
    })
    expect(setAccessTokenMock).toHaveBeenCalledWith('server-token')
    expect(setUserMock).toHaveBeenCalledWith(
      expect.objectContaining({
        name: 'root',
        mustChangePassword: false,
      })
    )
    expect(navigate).toHaveBeenCalledWith({ to: '/', replace: true })
  })

  it('有安全的 redirect 时跳转到 redirect 目标', async () => {
    const screen = await render(<UserAuthForm redirectTo='/system/users' />)

    await userEvent.click(screen.getByRole('button', { name: /登录/ }))

    await vi.waitFor(() =>
      expect(navigate).toHaveBeenCalledWith({
        to: '/system/users',
        replace: true,
      })
    )
  })

  it('强制改密账号跳转账号安全页', async () => {
    postMock.mockResolvedValueOnce({
      data: {
        ...loginResponse.data,
        data: {
          ...loginResponse.data.data,
          user: {
            ...loginResponse.data.data.user,
            mustChangePassword: 1,
          },
        },
      },
    })
    const screen = await render(<UserAuthForm />)

    await userEvent.click(screen.getByRole('button', { name: /登录/ }))

    await vi.waitFor(() =>
      expect(navigate).toHaveBeenCalledWith({
        to: '/settings/account',
        replace: true,
      })
    )
  })
})
