import { flushPromises, mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createI18n } from 'vue-i18n'
import { createMemoryHistory, createRouter } from 'vue-router'

import zhCN from '@/i18n/locales/zh-CN'
import { ApiError } from '@/services/httpClient'
import { useAuthStore } from '@/stores/authStore'
import LoginView from '@/views/auth/LoginView.vue'

vi.mock('@/services/authService', async (importOriginal) => {
  const actual = await importOriginal<typeof import('@/services/authService')>()
  return {
    ...actual,
    loginAuth: vi.fn(),
  }
})

const authService = await import('@/services/authService')

function createAuthPayload() {
  return {
    access_token: 'session-token',
    token_type: 'Bearer',
    expires_at: '2026-07-09T12:00:00Z',
    user: {
      id: '1900000000000000001',
      username: 'admin',
      display_name: '系统管理员',
      super_admin: true,
    },
    default_hotel_id: 'HOTEL-TEST',
    hotels: [
      {
        hotel_id: 'HOTEL-TEST',
        hotel_name: '测试酒店',
        time_zone: 'Asia/Bangkok',
        default_hotel: true,
      },
    ],
    permissions: ['RESERVATION_ORDER_READ'],
    menus: [
      {
        menu_code: 'RESERVATION_ORDERS',
        menu_name: '订单列表',
        route_path: '/reservation/orders',
        component_key: 'ReservationOrders',
        icon_key: 'pi pi-list',
        permission_code: 'RESERVATION_ORDER_READ',
        sort_order: 10,
      },
    ],
  }
}

async function mountLoginView(redirect = '/reservation/orders') {
  const pinia = createPinia()
  setActivePinia(pinia)
  const i18n = createI18n({
    legacy: false,
    locale: 'zh-CN',
    messages: {
      'zh-CN': zhCN,
    },
  })
  const router = createRouter({
    history: createMemoryHistory(),
    routes: [
      { path: '/login', component: LoginView },
      { path: '/reservation/orders', component: { template: '<div />' } },
      { path: '/reservation/tasks', component: { template: '<div />' } },
    ],
  })
  await router.push({ path: '/login', query: { redirect } })
  await router.isReady()

  const wrapper = mount(LoginView, {
    global: {
      plugins: [pinia, i18n, router],
    },
  })

  return {
    wrapper,
    router,
    authStore: useAuthStore(),
  }
}

describe('LoginView', () => {
  beforeEach(() => {
    vi.mocked(authService.loginAuth).mockReset()
    sessionStorage.clear()
    localStorage.clear()
  })

  it('logs in and redirects to the original protected route', async () => {
    vi.mocked(authService.loginAuth).mockResolvedValue(createAuthPayload())
    const { wrapper, router, authStore } = await mountLoginView('/reservation/tasks')

    await wrapper.find('input[name="username"]').setValue('admin')
    await wrapper.find('input[name="password"]').setValue('Admin@123456')
    await wrapper.find('form').trigger('submit')
    await flushPromises()

    expect(authService.loginAuth).toHaveBeenCalledWith({
      username: 'admin',
      password: 'Admin@123456',
      preferred_hotel_id: undefined,
    })
    expect(authStore.user?.username).toBe('admin')
    expect(router.currentRoute.value.fullPath).toBe('/reservation/tasks')
  })

  it('falls back to the first menu path when the login redirect points to root', async () => {
    vi.mocked(authService.loginAuth).mockResolvedValue(createAuthPayload())
    const { wrapper, router } = await mountLoginView('/')

    await wrapper.find('input[name="username"]').setValue('admin')
    await wrapper.find('input[name="password"]').setValue('Admin@123456')
    await wrapper.find('form').trigger('submit')
    await flushPromises()

    expect(router.currentRoute.value.fullPath).toBe('/reservation/orders')
    expect(wrapper.text()).toContain('登录')
    expect(wrapper.text()).not.toContain('登录中')
  })

  it('shows a safe login failure message without storing the token', async () => {
    vi.mocked(authService.loginAuth).mockRejectedValue(
      new ApiError('用户名或密码错误。', 401, {
        error_code: 'AUTH_INVALID_CREDENTIALS',
        message: '用户名或密码错误。',
      }),
    )
    const { wrapper } = await mountLoginView()

    await wrapper.find('input[name="username"]').setValue('admin')
    await wrapper.find('input[name="password"]').setValue('wrong-password')
    await wrapper.find('form').trigger('submit')
    await flushPromises()

    expect(wrapper.text()).toContain('用户名或密码错误')
    expect(sessionStorage.getItem('th_hotel_access_token')).toBeNull()
    expect(localStorage.getItem('th_hotel_access_token')).toBeNull()
  })
})
