/**
 * 个人中心页面组件测试
 */

import React from 'react'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import ProfilePage from '../../src/pages/profile/index'

// 导入 Taro mock 函数
import taroMock from '../../tests/__mocks__/taroMock'

// Mock TabBarLayout 组件
jest.mock('@/layouts/tab-bar-layout', () => ({
  TabBarLayout: jest.fn(({ children, activeKey, className }) => (
    <div data-testid="tab-bar-layout" data-active-key={activeKey} className={className}>
      {children}
    </div>
  ))
}))

// Mock Navbar 组件
jest.mock('@/components/ui/navbar', () => ({
  Navbar: jest.fn(({ title, rightIcon, onClickRight, leftIcon, backgroundColor, textColor, border }) => (
    <div
      data-testid="navbar"
      data-title={title}
      data-right-icon={rightIcon}
      data-left-icon={leftIcon}
      data-background-color={backgroundColor}
      data-text-color={textColor}
      data-border={border}
    >
      <button data-testid="navbar-right-button" onClick={onClickRight}>
        {rightIcon}
      </button>
      <h1>{title}</h1>
    </div>
  ))
}))

// Mock AvatarUpload 组件
jest.mock('@/components/ui/avatar-upload', () => ({
  AvatarUpload: jest.fn(({ currentAvatar, onUploadSuccess, onUploadError, size, editable, className }) => (
    <div
      data-testid="avatar-upload"
      data-current-avatar={currentAvatar}
      data-size={size}
      data-editable={editable}
      className={className}
    >
      <button
        data-testid="avatar-upload-button"
        onClick={() => onUploadSuccess({ fileId: 'test-file-id', fullUrl: 'https://example.com/avatar.jpg' })}
      >
        上传头像
      </button>
      <button
        data-testid="avatar-upload-error-button"
        onClick={() => onUploadError(new Error('Upload failed'))}
      >
        上传失败
      </button>
    </div>
  ))
}))

// Mock Button 组件
jest.mock('@/components/ui/button', () => ({
  Button: jest.fn(({ children, variant, size, onClick, className }) => (
    <button
      data-testid="button"
      data-variant={variant}
      data-size={size}
      className={className}
      onClick={onClick}
    >
      {children}
    </button>
  ))
}))

// Mock FAQDialog 组件
jest.mock('@/components/FAQDialog', () => ({
  FAQDialog: jest.fn(({ open, onOpenChange }) => (
    <div data-testid="faq-dialog" data-open={open}>
      <button
        data-testid="faq-dialog-close"
        onClick={() => onOpenChange(false)}
      >
        关闭常见问题
      </button>
      <div data-testid="faq-content">常见问题内容</div>
    </div>
  ))
}))

// Mock useAuth hook
const mockUser = {
  id: 1,
  username: '测试用户',
  avatarFile: {
    fullUrl: 'https://example.com/avatar.jpg'
  }
}

const mockLogout = jest.fn()
const mockUpdateUser = jest.fn()

jest.mock('@/utils/auth', () => ({
  useAuth: jest.fn(() => ({
    user: mockUser,
    logout: mockLogout,
    isLoading: false,
    updateUser: mockUpdateUser
  }))
}))

// Mock React Query hooks
const mockUseQuery = jest.fn()
const mockUseMutation = jest.fn()

jest.mock('@tanstack/react-query', () => {
  const actual = jest.requireActual('@tanstack/react-query')
  return {
    ...actual,
    useQuery: (options: any) => mockUseQuery(options),
    useMutation: (options: any) => mockUseMutation(options)
  }
})


// 创建测试用的 QueryClient
const createTestQueryClient = () => new QueryClient({
  defaultOptions: {
    queries: {
      retry: false,
    },
  },
})

// 包装组件
const Wrapper = ({ children }: { children: React.ReactNode }) => {
  const queryClient = createTestQueryClient()
  return (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  )
}

describe('个人中心页面测试', () => {
  beforeEach(() => {
    jest.clearAllMocks()

    // 设置环境变量
    process.env.TARO_APP_WX_CORP_ID = 'wwc6d7911e2d23b7fb'
    process.env.TARO_APP_WX_KEFU_URL = 'https://work.weixin.qq.com/kfid/kfc5f4d729bc3c893d7'

    // 初始化 React Query mock
    mockUseQuery.mockImplementation(() => ({
      data: null,
      isLoading: false
    }))

    mockUseMutation.mockImplementation((options) => ({
      mutateAsync: options.mutationFn,
      isPending: false
    }))

    // 重置所有 mock 调用记录
    taroMock.showToast.mockClear()
    taroMock.openCustomerServiceChat.mockClear()
    taroMock.navigateTo.mockClear()
    taroMock.showLoading.mockClear()
    taroMock.hideLoading.mockClear()
    taroMock.showModal.mockClear()
    taroMock.reLaunch.mockClear()
  })

  test('应该正确渲染个人中心页面', () => {
    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 检查页面标题
    expect(screen.getByText('个人中心')).toBeInTheDocument()

    // 检查用户信息
    expect(screen.getByText('普通用户')).toBeInTheDocument()
    expect(screen.getByText('ID: 1')).toBeInTheDocument()

    // 检查功能菜单
    expect(screen.getByText('我的服务')).toBeInTheDocument()
    expect(screen.getByText('编辑资料')).toBeInTheDocument()
    expect(screen.getByText('乘车人管理')).toBeInTheDocument()
    expect(screen.getByText('设置')).toBeInTheDocument()
    expect(screen.getByText('隐私政策')).toBeInTheDocument()
    expect(screen.getByText('帮助与反馈')).toBeInTheDocument()

    // 检查客服与帮助区域
    expect(screen.getByText('客服与帮助')).toBeInTheDocument()
    expect(screen.getByText('联系客服')).toBeInTheDocument()
    expect(screen.getByText('7x24小时在线客服')).toBeInTheDocument()
    expect(screen.getByText('常见问题')).toBeInTheDocument()
    expect(screen.getByText('意见反馈')).toBeInTheDocument()

    // 检查版本信息
    expect(screen.getByText('去看出行 v1.0.0')).toBeInTheDocument()
  })

  test('应该处理联系客服功能 - 成功场景', async () => {
    taroMock.openCustomerServiceChat.mockImplementation((options) => {
      options.success()
    })

    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击联系客服按钮
    const customerServiceButton = screen.getByTestId('customer-service-button')
    fireEvent.click(customerServiceButton)

    // 检查微信客服API被正确调用
    await waitFor(() => {
      expect(taroMock.openCustomerServiceChat).toHaveBeenCalledWith({
        extInfo: {
          url: 'https://work.weixin.qq.com/kfid/kfc5f4d729bc3c893d7'
        },
        corpId: 'wwc6d7911e2d23b7fb',
        success: expect.any(Function),
        fail: expect.any(Function)
      })
    })
  })

  test('应该处理联系客服功能 - 失败场景', async () => {
    taroMock.openCustomerServiceChat.mockImplementation((options) => {
      options.fail({ errMsg: '客服功能不可用' })
    })

    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击联系客服按钮
    const customerServiceButton = screen.getByTestId('customer-service-button')
    fireEvent.click(customerServiceButton)

    // 检查错误提示显示
    await waitFor(() => {
      expect(taroMock.showToast).toHaveBeenCalledWith({
        title: '客服功能暂不可用，请稍后重试',
        icon: 'none'
      })
    })
  })

  test('应该处理联系客服功能 - 异常场景', async () => {
    taroMock.openCustomerServiceChat.mockImplementation(() => {
      throw new Error('API调用异常')
    })

    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击联系客服按钮
    const customerServiceButton = screen.getByTestId('customer-service-button')
    fireEvent.click(customerServiceButton)

    // 检查异常处理
    await waitFor(() => {
      expect(taroMock.showToast).toHaveBeenCalledWith({
        title: '客服功能异常，请稍后重试',
        icon: 'none'
      })
    })
  })

  test('应该处理其他功能按钮点击', () => {
    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击编辑资料按钮
    const editProfileButton = screen.getByTestId('edit-profile-button')
    fireEvent.click(editProfileButton)
    expect(taroMock.showToast).toHaveBeenCalledWith({
      title: '功能开发中...',
      icon: 'none'
    })

    // 点击乘车人管理按钮
    const passengersButton = screen.getByTestId('passengers-button')
    fireEvent.click(passengersButton)
    expect(taroMock.navigateTo).toHaveBeenCalledWith({
      url: '/pages/passengers/passengers'
    })

    // 点击设置按钮
    const settingsButton = screen.getByTestId('settings-button')
    fireEvent.click(settingsButton)
    expect(taroMock.showToast).toHaveBeenCalledWith({
      title: '功能开发中...',
      icon: 'none'
    })

    // 点击常见问题按钮 - 现在应该打开弹窗而不是显示Toast
    const faqButton = screen.getByTestId('faq-button')
    fireEvent.click(faqButton)
    // 检查弹窗状态变为打开
    const faqDialog = screen.getByTestId('faq-dialog')
    expect(faqDialog).toHaveAttribute('data-open', 'true')

    // 点击意见反馈按钮
    const feedbackButton = screen.getByTestId('feedback-button')
    fireEvent.click(feedbackButton)
    expect(taroMock.showToast).toHaveBeenCalledWith({
      title: '意见反馈功能开发中...',
      icon: 'none'
    })
  })

  test('应该处理头像上传功能', async () => {
    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击头像上传成功按钮
    const uploadButton = screen.getByTestId('avatar-upload-button')
    fireEvent.click(uploadButton)

    // 检查上传成功处理
    await waitFor(() => {
      expect(taroMock.showLoading).toHaveBeenCalledWith({ title: '更新头像...' })
      expect(taroMock.hideLoading).toHaveBeenCalled()
      expect(taroMock.showToast).toHaveBeenCalledWith({
        title: '头像更新成功',
        icon: 'success'
      })
      expect(mockUpdateUser).toHaveBeenCalledWith({
        ...mockUser,
        avatarFileId: 'test-file-id'
      })
    })
  })

  test('应该处理头像上传失败', async () => {
    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击头像上传失败按钮
    const uploadErrorButton = screen.getByTestId('avatar-upload-error-button')
    fireEvent.click(uploadErrorButton)

    // 检查上传失败处理
    await waitFor(() => {
      expect(taroMock.showToast).toHaveBeenCalledWith({
        title: '上传失败，请重试',
        icon: 'none'
      })
    })
  })

  // 退出登录功能暂时被注释掉，跳过相关测试
  test.skip('应该处理退出登录', async () => {
    taroMock.showModal.mockImplementation((options) => {
      options.success({ confirm: true })
    })

    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击退出登录按钮
    const logoutButton = screen.getByText('退出登录')
    fireEvent.click(logoutButton)

    // 检查退出登录流程
    await waitFor(() => {
      expect(taroMock.showModal).toHaveBeenCalledWith({
        title: '退出登录',
        content: '确定要退出登录吗？',
        success: expect.any(Function)
      })
      expect(taroMock.showLoading).toHaveBeenCalledWith({ title: '退出中...' })
      expect(mockLogout).toHaveBeenCalled()
      expect(taroMock.hideLoading).toHaveBeenCalled()
      expect(taroMock.showToast).toHaveBeenCalledWith({
        title: '已退出登录',
        icon: 'success',
        duration: 1500
      })
    })
  })

  test.skip('应该处理退出登录取消', async () => {
    taroMock.showModal.mockImplementation((options) => {
      options.success({ confirm: false })
    })

    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击退出登录按钮
    const logoutButton = screen.getByText('退出登录')
    fireEvent.click(logoutButton)

    // 检查取消退出登录
    await waitFor(() => {
      expect(taroMock.showModal).toHaveBeenCalled()
      expect(mockLogout).not.toHaveBeenCalled()
    })
  })

  test('应该正确使用TabBarLayout', () => {
    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 检查TabBarLayout是否正确使用
    const tabBarLayout = screen.getByTestId('tab-bar-layout')
    expect(tabBarLayout).toHaveAttribute('data-active-key', 'profile')
  })

  test('应该正确使用Navbar', () => {
    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 检查Navbar是否正确使用
    const navbar = screen.getByTestId('navbar')
    expect(navbar).toHaveAttribute('data-title', '个人中心')
    expect(navbar).toHaveAttribute('data-right-icon', 'i-heroicons-cog-6-tooth-20-solid')
    expect(navbar).toHaveAttribute('data-background-color', 'bg-primary')
    expect(navbar).toHaveAttribute('data-text-color', 'text-white')
    expect(navbar).toHaveAttribute('data-border', 'false')
  })

  test('应该显示默认头像当用户无头像时', () => {
    // 模拟用户无头像的情况
    const mockUseAuth = jest.requireMock('@/utils/auth').useAuth
    mockUseAuth.mockImplementation(() => ({
      user: {
        ...mockUser,
        avatarFile: null
      },
      logout: mockLogout,
      isLoading: false,
      updateUser: mockUpdateUser
    }))

    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 检查默认头像路径
    const avatarUpload = screen.getByTestId('avatar-upload')
    expect(avatarUpload).toHaveAttribute('data-current-avatar', '/images/default_avatar.jpg')
  })

  test('应该显示默认用户名', () => {
    // 模拟用户无用户名的情况
    const mockUseAuth = jest.requireMock('@/utils/auth').useAuth
    mockUseAuth.mockImplementation(() => ({
      user: {
        ...mockUser,
        username: ''
      },
      logout: mockLogout,
      isLoading: false,
      updateUser: mockUpdateUser
    }))

    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 检查用户名显示为"普通用户"
    expect(screen.getByText('普通用户')).toBeInTheDocument()
  })

  test('头像上传功能应该在默认头像状态下正常工作', async () => {
    // 模拟用户无头像的情况
    const mockUseAuth = jest.requireMock('@/utils/auth').useAuth
    mockUseAuth.mockImplementation(() => ({
      user: {
        ...mockUser,
        avatarFile: null
      },
      logout: mockLogout,
      isLoading: false,
      updateUser: mockUpdateUser
    }))

    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 点击头像上传成功按钮
    const uploadButton = screen.getByTestId('avatar-upload-button')
    fireEvent.click(uploadButton)

    // 检查上传成功处理
    await waitFor(() => {
      expect(taroMock.showLoading).toHaveBeenCalledWith({ title: '更新头像...' })
      expect(taroMock.hideLoading).toHaveBeenCalled()
      expect(taroMock.showToast).toHaveBeenCalledWith({
        title: '头像更新成功',
        icon: 'success'
      })
      expect(mockUpdateUser).toHaveBeenCalledWith({
        ...mockUser,
        avatarFile: null,
        avatarFileId: 'test-file-id'
      })
    })
  })

  test('应该正确处理常见问题弹窗的打开和关闭', () => {
    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 初始状态下弹窗应该是关闭的
    const faqDialog = screen.getByTestId('faq-dialog')
    expect(faqDialog).toHaveAttribute('data-open', 'false')

    // 点击常见问题按钮打开弹窗
    const faqButton = screen.getByTestId('faq-button')
    fireEvent.click(faqButton)

    // 检查弹窗状态变为打开
    expect(faqDialog).toHaveAttribute('data-open', 'true')

    // 点击关闭按钮关闭弹窗
    const closeButton = screen.getByTestId('faq-dialog-close')
    fireEvent.click(closeButton)

    // 检查弹窗状态变为关闭
    expect(faqDialog).toHaveAttribute('data-open', 'false')
  })

  test('常见问题弹窗应该显示正确的内容', () => {
    render(
      <Wrapper>
        <ProfilePage />
      </Wrapper>
    )

    // 打开常见问题弹窗
    const faqButton = screen.getByTestId('faq-button')
    fireEvent.click(faqButton)

    // 检查弹窗内容是否正确显示
    const faqContent = screen.getByTestId('faq-content')
    expect(faqContent).toBeInTheDocument()
    expect(faqContent).toHaveTextContent('常见问题内容')
  })
})