import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { createI18n } from 'vue-i18n'
import LoginView from '@/views/login/index.vue'
import { useUserStore } from '@/store/user'
import { wrapResponse, wrapErrorResponse, mockLoginResponse } from '../../../fixtures'

// Mock vue-router
const mockPush = vi.fn()
const mockRoute = { query: {} }
vi.mock('vue-router', () => ({
  useRouter: () => ({ push: mockPush }),
  useRoute: () => mockRoute
}))

// Mock element-plus
vi.mock('element-plus', () => ({
  ElMessage: {
    success: vi.fn(),
    error: vi.fn(),
    info: vi.fn()
  }
}))

// Mock __APP_VERSION__
vi.stubGlobal('__APP_VERSION__', '1.0.0')

// Create i18n instance for tests
const i18n = createI18n({
  legacy: false,
  locale: 'zh-CN',
  messages: {
    'zh-CN': {
      用户名: '用户名',
      密码: '密码',
      登录: '登录',
      记住我: '记住我',
      请输入用户名: '请输入用户名',
      请输入密码: '请输入密码',
      登录成功: '登录成功',
      登录失败: '登录失败',
      '登录失败，请检查网络': '登录失败，请检查网络',
      摄像头管理系统: '摄像头管理系统',
      欢迎回来: '欢迎回来',
      '登录您的管理后台，开始管理您的业务': '登录您的管理后台，开始管理您的业务',
      用户: '用户',
      稳定性: '稳定性',
      技术支持: '技术支持',
      '忘记密码？': '忘记密码？',
      请联系管理员重置密码: '请联系管理员重置密码'
    }
  }
})

describe('Login View', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    vi.clearAllMocks()
    mockPush.mockClear()
    mockRoute.query = {}
    localStorage.clear()
  })

  const mountLogin = () => {
    return mount(LoginView, {
      global: {
        plugins: [createPinia(), i18n],
        stubs: {
          LangDropdown: true
        }
      }
    })
  }

  describe('表单渲染', () => {
    it('应该正确渲染登录表单', () => {
      const wrapper = mountLogin()

      expect(wrapper.find('input[placeholder="用户名"]').exists()).toBe(true)
      expect(wrapper.find('input[placeholder="密码"]').exists()).toBe(true)
      expect(wrapper.find('button[type="submit"]').exists()).toBe(true)
    })

    it('密码输入框默认为密码类型', () => {
      const wrapper = mountLogin()
      const passwordInput = wrapper.find('input[placeholder="密码"]')

      expect(passwordInput.attributes('type')).toBe('password')
    })

    it('点击显示密码按钮切换密码可见性', async () => {
      const wrapper = mountLogin()
      const passwordInput = wrapper.find('input[placeholder="密码"]')
      const toggleBtn = wrapper.find('.login__password-toggle')

      expect(passwordInput.attributes('type')).toBe('password')

      await toggleBtn.trigger('click')
      expect(passwordInput.attributes('type')).toBe('text')

      await toggleBtn.trigger('click')
      expect(passwordInput.attributes('type')).toBe('password')
    })
  })

  describe('表单验证', () => {
    it('空用户名提交显示错误', async () => {
      const wrapper = mountLogin()

      await wrapper.find('input[placeholder="密码"]').setValue('password')
      await wrapper.find('form').trigger('submit')

      expect(wrapper.text()).toContain('请输入用户名')
    })

    it('空密码提交显示错误', async () => {
      const wrapper = mountLogin()

      await wrapper.find('input[placeholder="用户名"]').setValue('admin')
      await wrapper.find('form').trigger('submit')

      expect(wrapper.text()).toContain('请输入密码')
    })

    it('用户名和密码都为空时显示两个错误', async () => {
      const wrapper = mountLogin()

      await wrapper.find('form').trigger('submit')

      expect(wrapper.text()).toContain('请输入用户名')
      expect(wrapper.text()).toContain('请输入密码')
    })
  })

  describe('登录功能', () => {
    it('登录成功后跳转到首页', async () => {
      const wrapper = mountLogin()
      const userStore = useUserStore()

      // Mock loginAction
      vi.spyOn(userStore, 'loginAction').mockResolvedValue(wrapResponse(mockLoginResponse))

      await wrapper.find('input[placeholder="用户名"]').setValue('admin')
      await wrapper.find('input[placeholder="密码"]').setValue('123456')
      await wrapper.find('form').trigger('submit')
      await flushPromises()

      expect(userStore.loginAction).toHaveBeenCalledWith({
        username: 'admin',
        password: '123456'
      })
      expect(mockPush).toHaveBeenCalledWith('/')
    })

    it('登录成功后跳转到 redirect 参数指定的页面', async () => {
      mockRoute.query = { redirect: '/dashboard' }

      const wrapper = mountLogin()
      const userStore = useUserStore()

      vi.spyOn(userStore, 'loginAction').mockResolvedValue(wrapResponse(mockLoginResponse))

      await wrapper.find('input[placeholder="用户名"]').setValue('admin')
      await wrapper.find('input[placeholder="密码"]').setValue('123456')
      await wrapper.find('form').trigger('submit')
      await flushPromises()

      expect(mockPush).toHaveBeenCalledWith('/dashboard')
    })

    it('登录失败显示错误消息', async () => {
      const { ElMessage } = await import('element-plus')
      const wrapper = mountLogin()
      const userStore = useUserStore()

      vi.spyOn(userStore, 'loginAction').mockResolvedValue(wrapErrorResponse('用户名或密码错误', 401) as any)

      await wrapper.find('input[placeholder="用户名"]').setValue('admin')
      await wrapper.find('input[placeholder="密码"]').setValue('wrongpassword')
      await wrapper.find('form').trigger('submit')
      await flushPromises()

      expect(ElMessage.error).toHaveBeenCalledWith('用户名或密码错误')
      expect(mockPush).not.toHaveBeenCalled()
    })

    it('登录请求异常显示网络错误', async () => {
      const { ElMessage } = await import('element-plus')
      const wrapper = mountLogin()
      const userStore = useUserStore()

      vi.spyOn(userStore, 'loginAction').mockRejectedValue(new Error('Network Error'))

      await wrapper.find('input[placeholder="用户名"]').setValue('admin')
      await wrapper.find('input[placeholder="密码"]').setValue('123456')
      await wrapper.find('form').trigger('submit')
      await flushPromises()

      expect(ElMessage.error).toHaveBeenCalled()
      expect(mockPush).not.toHaveBeenCalled()
    })

    it('登录时显示加载状态', async () => {
      const wrapper = mountLogin()
      const userStore = useUserStore()

      // Mock a slow login
      vi.spyOn(userStore, 'loginAction').mockImplementation(
        () => new Promise((resolve) => setTimeout(() => resolve(wrapResponse(mockLoginResponse)), 100))
      )

      await wrapper.find('input[placeholder="用户名"]').setValue('admin')
      await wrapper.find('input[placeholder="密码"]').setValue('123456')
      await wrapper.find('form').trigger('submit')

      // Button should be disabled during loading
      const submitBtn = wrapper.find('button[type="submit"]')
      expect(submitBtn.attributes('disabled')).toBeDefined()

      await flushPromises()
    })
  })

  describe('记住我功能', () => {
    it('记住我选中时保存用户名到 localStorage', async () => {
      const wrapper = mountLogin()
      const userStore = useUserStore()

      vi.spyOn(userStore, 'loginAction').mockResolvedValue(wrapResponse(mockLoginResponse))

      const checkbox = wrapper.find('.login__checkbox')
      await checkbox.setValue(true)

      await wrapper.find('input[placeholder="用户名"]').setValue('admin')
      await wrapper.find('input[placeholder="密码"]').setValue('123456')
      await wrapper.find('form').trigger('submit')
      await flushPromises()

      expect(localStorage.getItem('login_remember')).toBe('admin')
    })

    it('记住我未选中时不保存用户名', async () => {
      const wrapper = mountLogin()
      const userStore = useUserStore()

      vi.spyOn(userStore, 'loginAction').mockResolvedValue(wrapResponse(mockLoginResponse))

      const checkbox = wrapper.find('.login__checkbox')
      await checkbox.setValue(false)

      await wrapper.find('input[placeholder="用户名"]').setValue('admin')
      await wrapper.find('input[placeholder="密码"]').setValue('123456')
      await wrapper.find('form').trigger('submit')
      await flushPromises()

      expect(localStorage.getItem('login_remember')).toBeNull()
    })

    it('页面加载时自动填充保存的用户名', async () => {
      localStorage.setItem('login_remember', 'saveduser')

      const wrapper = mountLogin()
      await flushPromises()

      const usernameInput = wrapper.find('input[placeholder="用户名"]')
      expect((usernameInput.element as HTMLInputElement).value).toBe('saveduser')
    })
  })
})
