import React from 'react'
import { render, waitFor, fireEvent } from '@testing-library/react-native'
import My from '../my'

// Mock react-native-safe-area-context FIRST
jest.mock('react-native-safe-area-context', () => ({
  SafeAreaProvider: ({ children }: any) => children,
  SafeAreaView: ({ children }: any) => children,
  useSafeAreaInsets: () => ({ top: 0, right: 0, bottom: 0, left: 0 }),
}))

// Mock expo-status-bar
jest.mock('expo-status-bar', () => ({
  StatusBar: 'StatusBar',
}))

// Mock expo-image
jest.mock('expo-image', () => ({
  Image: 'Image',
}))

jest.mock('expo-router', () => ({
  useRouter: () => ({
    push: jest.fn(),
    replace: jest.fn(),
  }),
}))

jest.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string) => key,
    i18n: { language: 'zh-CN', changeLanguage: jest.fn() },
  }),
}))

jest.mock('@/lib/auth', () => ({
  signOut: jest.fn(),
  useSession: () => ({
    data: {
      user: {
        id: 'test-user-id',
        name: 'Test User',
        username: 'testuser',
        image: null,
      },
    },
  }),
}))

jest.mock('@/hooks/use-user-balance', () => ({
  useUserBalance: () => ({
    balance: 100,
  }),
}))

jest.mock('@/components/skeleton/MySkeleton', () => ({
  MySkeleton: () => 'MySkeleton',
}))

jest.mock('@/components/icon', () => ({
  PointsIcon: () => 'PointsIcon',
  SearchIcon: () => 'SearchIcon',
  SettingsIcon: () => 'SettingsIcon',
}))

jest.mock('@/components/drawer/EditProfileDrawer', () => ({
  __esModule: true,
  default: () => 'EditProfileDrawer',
}))

jest.mock('@/components/ui/dropdown', () => ({
  __esModule: true,
  default: () => 'Dropdown',
}))

jest.mock('@/components/ui/Toast', () => ({
  __esModule: true,
  default: {
    show: jest.fn(),
    showLoading: jest.fn(),
    hideLoading: jest.fn(),
    showActionSheet: jest.fn(),
  },
}))

jest.mock('expo-image', () => ({
  Image: 'Image',
}))

const mockRefetch = jest.fn()
const mockLoadMore = jest.fn()

jest.mock('@/hooks', () => ({
  useTemplateGenerations: jest.fn(() => ({
    generations: [],
    loading: false,
    loadingMore: false,
    refetch: mockRefetch,
    loadMore: mockLoadMore,
    hasMore: true,
  })),
}))

describe('My Page - Pagination', () => {
  beforeEach(() => {
    jest.clearAllMocks()
  })

  it('should load first page with limit 20 on mount', async () => {
    render(<My />)

    await waitFor(() => {
      expect(mockRefetch).toHaveBeenCalledWith({ page: 1, limit: 20 })
    })
  })

  it('should refresh with limit 20 on pull to refresh', async () => {
    const { useTemplateGenerations } = require('@/hooks')
    const mockRefetchAsync = jest.fn().mockResolvedValue({ data: [], error: null })

    useTemplateGenerations.mockReturnValue({
      generations: [{ id: '1', status: 'completed' }],
      loading: false,
      loadingMore: false,
      refetch: mockRefetchAsync,
      loadMore: mockLoadMore,
      hasMore: true,
    })

    const { getByTestId } = render(<My />)

    // 模拟下拉刷新
    const scrollView = getByTestId('my-scroll-view')
    const refreshControl = scrollView.props.refreshControl

    // 触发刷新
    await refreshControl.props.onRefresh()

    await waitFor(() => {
      expect(mockRefetchAsync).toHaveBeenCalledWith({ page: 1, limit: 20 })
    })
  })

  it('should stop showing refreshing indicator after refresh completes', async () => {
    const { useTemplateGenerations } = require('@/hooks')
    let resolveRefetch: any
    const mockRefetchAsync = jest.fn(() => new Promise((resolve) => {
      resolveRefetch = resolve
    }))

    useTemplateGenerations.mockReturnValue({
      generations: [{ id: '1', status: 'completed' }],
      loading: false,
      loadingMore: false,
      refetch: mockRefetchAsync,
      loadMore: mockLoadMore,
      hasMore: true,
    })

    const { getByTestId } = render(<My />)
    const scrollView = getByTestId('my-scroll-view')
    const refreshControl = scrollView.props.refreshControl

    // 开始刷新
    const refreshPromise = refreshControl.props.onRefresh()

    // 刷新中应该显示 refreshing
    await waitFor(() => {
      expect(refreshControl.props.refreshing).toBe(true)
    })

    // 完成刷新
    resolveRefetch({ data: [], error: null })
    await refreshPromise

    // 刷新完成后应该隐藏 refreshing
    await waitFor(() => {
      expect(refreshControl.props.refreshing).toBe(false)
    })
  })

  it('should call loadMore when scrolling near bottom', async () => {
    const { useTemplateGenerations } = require('@/hooks')

    useTemplateGenerations.mockReturnValue({
      generations: Array(20).fill(null).map((_, i) => ({
        id: `${i}`,
        status: 'completed',
        resultUrl: ['url'],
      })),
      loading: false,
      loadingMore: false,
      refetch: mockRefetch,
      loadMore: mockLoadMore,
      hasMore: true,
    })

    const { getByTestId } = render(<My />)
    const scrollView = getByTestId('my-scroll-view')

    // 模拟滚动到底部
    const scrollEvent = {
      nativeEvent: {
        layoutMeasurement: { height: 800 },
        contentOffset: { y: 1000 },
        contentSize: { height: 1800 }, // 距离底部 < 100px
      },
    }

    fireEvent.scroll(scrollView, scrollEvent)

    await waitFor(() => {
      expect(mockLoadMore).toHaveBeenCalled()
    })
  })

  it('should not load more when loadingMore is true', async () => {
    const { useTemplateGenerations } = require('@/hooks')

    useTemplateGenerations.mockReturnValue({
      generations: Array(20).fill(null).map((_, i) => ({
        id: `${i}`,
        status: 'completed'
      })),
      loading: false,
      loadingMore: true,
      refetch: mockRefetch,
      loadMore: mockLoadMore,
      hasMore: true,
    })

    render(<My />)

    await waitFor(() => {
      expect(mockRefetch).toHaveBeenCalledWith({ page: 1, limit: 20 })
    })
  })

  it('should not load more when hasMore is false', async () => {
    const { useTemplateGenerations } = require('@/hooks')

    useTemplateGenerations.mockReturnValue({
      generations: Array(10).fill(null).map((_, i) => ({
        id: `${i}`,
        status: 'completed'
      })),
      loading: false,
      loadingMore: false,
      refetch: mockRefetch,
      loadMore: mockLoadMore,
      hasMore: false,
    })

    render(<My />)

    await waitFor(() => {
      expect(mockRefetch).toHaveBeenCalledWith({ page: 1, limit: 20 })
    })
  })
})
