/**
 * PersonalInfoPage 页面测试
 * 使用真实的React Query和RPC类型验证
 */
import React from 'react'
import { render, screen, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import PersonalInfoPage from '../../../src/pages/PersonalInfoPage/PersonalInfoPage'
import { talentPersonalInfoClient } from '../../../src/api'
import { useRequireAuth } from '@d8d/rencai-auth-ui/hooks'
import Taro from '@tarojs/taro'

// Mock 认证 hooks
jest.mock('@d8d/rencai-auth-ui/hooks', () => ({
  useRequireAuth: jest.fn()
}))

// Mock API 客户端 - 使用真实的RPC类型
jest.mock('../../../src/api', () => ({
  talentPersonalInfoClient: {
    personal: {
      info: {
        $get: jest.fn()
      },
      'bank-cards': {
        $get: jest.fn()
      },
      photos: {
        $get: jest.fn()
      }
    }
  }
}))

// Mock 布局组件
jest.mock('@d8d/rencai-shared-ui/components/RencaiTabBarLayout', () => ({
  RencaiTabBarLayout: ({ children }: { children: React.ReactNode }) => <div data-testid="tabbar-layout">{children}</div>
}))

// Mock 导航栏组件
jest.mock('@d8d/mini-shared-ui-components/components/navbar', () => ({
  Navbar: ({ title }: { title: string }) => <div data-testid="navbar">{title}</div>
}))

const createMockResponse = <T,>(status: number, data: T) => ({
  status,
  ok: status >= 200 && status < 300,
  json: async () => data
})

const createTestWrapper = () => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
        staleTime: Infinity,
        refetchOnWindowFocus: false,
        refetchOnReconnect: false
      }
    }
  })

  return ({ children }: { children: React.ReactNode }) => (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  )
}

describe('PersonalInfoPage', () => {
  beforeEach(() => {
    jest.clearAllMocks()
    // Mock useRequireAuth 使其不做任何操作（用户已认证）
    ;(useRequireAuth as jest.Mock).mockImplementation(() => {})
    // 清理 Taro API mock
    ;(Taro.setNavigationBarTitle as jest.Mock).mockClear()
    ;(Taro.showToast as jest.Mock).mockClear()
  })

  it('应该渲染带有正确标题的导航栏', async () => {
    // Mock API 调用 - 使用符合RPC类型的响应
    ;(talentPersonalInfoClient.personal.info.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, {} as any)
    )
    ;(talentPersonalInfoClient.personal['bank-cards'].$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )
    ;(talentPersonalInfoClient.personal.photos.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )

    const wrapper = createTestWrapper()
    render(<PersonalInfoPage />, { wrapper })

    // 检查导航栏是否渲染了正确的标题
    expect(screen.getByTestId('navbar')).toHaveTextContent('个人信息')
    expect(Taro.setNavigationBarTitle).toHaveBeenCalledWith({ title: '个人信息' })
  })

  it('应该渲染顶部用户信息区域', async () => {
    // 符合RPC类型的个人信息数据
    const mockPersonalInfo = {
      name: '张三',
      gender: '男',
      idCard: '110101199001011234',
      disabilityId: 'D12345678901',
      disabilityType: '肢体残疾',
      disabilityLevel: '三级',
      phone: '13800138000',
      province: '北京市',
      city: '北京市',
      district: '朝阳区',
      detailedAddress: '某某街道123号',
      birthDate: '1990-01-01',
      idAddress: '北京市朝阳区某某街道123号',
      idValidDate: '2030-01-01',
      disabilityValidDate: '2025-12-31',
      canDirectContact: 1,
      isMarried: 0,
      nation: '汉族',
      jobStatus: 1,
      specificDisability: '左腿小腿截肢'
    }

    ;(talentPersonalInfoClient.personal.info.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, mockPersonalInfo)
    )
    ;(talentPersonalInfoClient.personal['bank-cards'].$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )
    ;(talentPersonalInfoClient.personal.photos.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )

    const wrapper = createTestWrapper()
    const { container } = render(<PersonalInfoPage />, { wrapper })

    await waitFor(() => {
      // 检查顶部用户信息区域 - 使用更精确的选择器
      expect(screen.getByText('肢体残疾 · 三级 · 在职')).toBeInTheDocument()
      // 检查渐变背景
      const gradientElement = container.querySelector('.bg-gradient-to-b')
      expect(gradientElement).toBeInTheDocument()
    })
  })

  it('应该渲染带有正确RPC类型的个人基本信息', async () => {
    // 符合RPC类型的个人信息数据
    const mockPersonalInfo = {
      name: '张三',
      gender: '男',
      idCard: '110101199001011234',
      disabilityId: 'D12345678901',
      disabilityType: '肢体残疾',
      disabilityLevel: '一级',
      phone: '13800138000',
      province: '北京市',
      city: '北京市',
      district: '朝阳区',
      detailedAddress: '某某街道123号',
      birthDate: '1990-01-01',
      idAddress: '北京市朝阳区某某街道123号',
      idValidDate: '2030-01-01',
      disabilityValidDate: '2025-12-31',
      canDirectContact: 1,
      isMarried: 0,
      nation: '汉族',
      jobStatus: 0,
      specificDisability: '左腿小腿截肢'
    }

    ;(talentPersonalInfoClient.personal.info.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, mockPersonalInfo)
    )
    ;(talentPersonalInfoClient.personal['bank-cards'].$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )
    ;(talentPersonalInfoClient.personal.photos.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )

    const wrapper = createTestWrapper()
    render(<PersonalInfoPage />, { wrapper })

    await waitFor(() => {
      // 使用 getAllByText 因为"张三"出现在顶部用户信息区域和个人基本信息卡片中
      expect(screen.getAllByText('张三')).toHaveLength(2)
      expect(screen.getByText('男')).toBeInTheDocument()
      expect(screen.getByText('肢体残疾')).toBeInTheDocument()
      expect(screen.getByText('一级')).toBeInTheDocument()
    })
  })

  it('应该渲染带有正确RPC类型的银行卡信息', async () => {
    // 符合RPC类型的银行卡数据
    const mockBankCards = [
      {
        id: 1,
        subBankName: '中国工商银行北京分行朝阳支行',
        bankName: '中国工商银行',
        cardNumber: '6222020200001234567',
        cardholderName: '张三',
        cardType: '一类卡',
        isDefault: 1,
        fileUrl: null
      }
    ]

    ;(talentPersonalInfoClient.personal.info.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, {} as any)
    )
    ;(talentPersonalInfoClient.personal['bank-cards'].$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: mockBankCards, total: 1 })
    )
    ;(talentPersonalInfoClient.personal.photos.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )

    const wrapper = createTestWrapper()
    render(<PersonalInfoPage />, { wrapper })

    await waitFor(() => {
      expect(screen.getByText('中国工商银行')).toBeInTheDocument()
      expect(screen.getByText('**** **** **** 4567')).toBeInTheDocument()
      expect(screen.getByText('默认')).toBeInTheDocument()
      expect(screen.getByText('一类卡')).toBeInTheDocument()
    })
  })

  it('应该渲染带有正确RPC类型的证件照片', async () => {
    // 符合RPC类型的证件照片数据
    const mockPhotos = [
      {
        id: 1,
        photoType: '身份证',
        fileUrl: 'https://example.com/id-card.jpg',
        fileName: '身份证.jpg',
        uploadTime: '2024-01-01T10:30:00Z',
        canDownload: 1
      }
    ]

    ;(talentPersonalInfoClient.personal.info.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, {} as any)
    )
    ;(talentPersonalInfoClient.personal['bank-cards'].$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )
    ;(talentPersonalInfoClient.personal.photos.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: mockPhotos, total: 1 })
    )

    const wrapper = createTestWrapper()
    render(<PersonalInfoPage />, { wrapper })

    await waitFor(() => {
      expect(screen.getByText('身份证')).toBeInTheDocument()
    })
  })

  it('应该在没有数据时显示空状态', async () => {
    ;(talentPersonalInfoClient.personal.info.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, {} as any)
    )
    ;(talentPersonalInfoClient.personal['bank-cards'].$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )
    ;(talentPersonalInfoClient.personal.photos.$get as jest.Mock).mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    )

    const wrapper = createTestWrapper()
    render(<PersonalInfoPage />, { wrapper })

    await waitFor(() => {
      expect(screen.getByText('暂无银行卡信息')).toBeInTheDocument()
      expect(screen.getByText('暂无证件照片')).toBeInTheDocument()
    })
  })

  it('应该在API调用失败时显示错误提示', async () => {
    // Mock API 错误
    ;(talentPersonalInfoClient.personal.info.$get as jest.Mock).mockRejectedValue(
      new Error('获取个人信息失败')
    )
    ;(talentPersonalInfoClient.personal['bank-cards'].$get as jest.Mock).mockRejectedValue(
      new Error('获取银行卡信息失败')
    )
    ;(talentPersonalInfoClient.personal.photos.$get as jest.Mock).mockRejectedValue(
      new Error('获取证件照片失败')
    )

    const wrapper = createTestWrapper()
    render(<PersonalInfoPage />, { wrapper })

    await waitFor(() => {
      expect(Taro.showToast).toHaveBeenCalled()
    })
  })
})
