import React from 'react'
import { render, fireEvent, waitFor } from '@testing-library/react-native'
import { View } from 'react-native'
import GenerationRecordScreen from './generationRecord'

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

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

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

jest.mock('react-native-safe-area-context', () => ({
    SafeAreaView: ({ children }: { children: React.ReactNode }) => (
        <View>{children}</View>
    ),
}))

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

jest.mock('@/components/icon', () => ({
    LeftArrowIcon: () => null,
    DeleteIcon: () => null,
    EditIcon: () => null,
    ChangeIcon: () => null,
    WhiteStarIcon: () => null,
}))

jest.mock('@/components/ui/delete-confirm-dialog', () => ({
    DeleteConfirmDialog: () => null,
}))

jest.mock('@/components/LoadingState', () => ({
    __esModule: true,
    default: ({ testID }: any) => <View testID={testID} />,
}))

jest.mock('@/components/ErrorState', () => ({
    __esModule: true,
    default: ({ testID }: any) => <View testID={testID} />,
}))

jest.mock('@/components/PaginationLoader', () => ({
    __esModule: true,
    default: ({ testID }: any) => <View testID={testID} />,
}))

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

jest.mock('@/hooks', () => ({
    useTemplateGenerations: jest.fn(),
}))

import { useTemplateGenerations } from '@/hooks'

const mockUseTemplateGenerations = useTemplateGenerations as jest.MockedFunction<typeof useTemplateGenerations>

describe('GenerationRecordScreen', () => {
    const mockExecute = jest.fn()
    const mockRefetch = jest.fn()
    const mockLoadMore = jest.fn()

    beforeEach(() => {
        jest.clearAllMocks()
    })

    it('shows loading state on initial load', () => {
        mockUseTemplateGenerations.mockReturnValue({
            generations: [],
            loading: true,
            loadingMore: false,
            error: null,
            execute: mockExecute,
            refetch: mockRefetch,
            loadMore: mockLoadMore,
            hasMore: true,
            data: undefined,
        })

        const { getByTestId } = render(<GenerationRecordScreen />)
        expect(getByTestId('loading-state')).toBeTruthy()
    })

    it('shows error state when error occurs', () => {
        mockUseTemplateGenerations.mockReturnValue({
            generations: [],
            loading: false,
            loadingMore: false,
            error: { message: 'Failed to load' } as any,
            execute: mockExecute,
            refetch: mockRefetch,
            loadMore: mockLoadMore,
            hasMore: false,
            data: undefined,
        })

        const { getByTestId } = render(<GenerationRecordScreen />)
        expect(getByTestId('error-state')).toBeTruthy()
    })

    it('renders generation list when data is loaded', () => {
        const mockGenerations = [
            {
                id: '1',
                template: { title: 'Test Template' },
                resultUrl: ['https://example.com/result.jpg'],
                originalUrl: 'https://example.com/original.jpg',
            },
        ]

        mockUseTemplateGenerations.mockReturnValue({
            generations: mockGenerations as any,
            loading: false,
            loadingMore: false,
            error: null,
            execute: mockExecute,
            refetch: mockRefetch,
            loadMore: mockLoadMore,
            hasMore: true,
            data: { data: mockGenerations } as any,
        })

        const { getByText } = render(<GenerationRecordScreen />)
        expect(getByText('Test Template')).toBeTruthy()
    })

    it('shows pagination loader when loading more', () => {
        const mockGenerations = [
            {
                id: '1',
                template: { title: 'Test Template' },
                resultUrl: ['https://example.com/result.jpg'],
            },
        ]

        mockUseTemplateGenerations.mockReturnValue({
            generations: mockGenerations as any,
            loading: false,
            loadingMore: true,
            error: null,
            execute: mockExecute,
            refetch: mockRefetch,
            loadMore: mockLoadMore,
            hasMore: true,
            data: { data: mockGenerations } as any,
        })

        const { getByTestId } = render(<GenerationRecordScreen />)
        expect(getByTestId('pagination-loader')).toBeTruthy()
    })

    it('calls execute on mount', () => {
        mockUseTemplateGenerations.mockReturnValue({
            generations: [],
            loading: false,
            loadingMore: false,
            error: null,
            execute: mockExecute,
            refetch: mockRefetch,
            loadMore: mockLoadMore,
            hasMore: false,
            data: undefined,
        })

        render(<GenerationRecordScreen />)
        expect(mockExecute).toHaveBeenCalledWith({ page: 1, limit: 20 })
    })

    it('calls refetch on pull to refresh', async () => {
        const mockGenerations = [
            {
                id: '1',
                template: { title: 'Test Template' },
                resultUrl: ['https://example.com/result.jpg'],
            },
        ]

        mockUseTemplateGenerations.mockReturnValue({
            generations: mockGenerations as any,
            loading: false,
            loadingMore: false,
            error: null,
            execute: mockExecute,
            refetch: mockRefetch,
            loadMore: mockLoadMore,
            hasMore: true,
            data: { data: mockGenerations } as any,
        })

        const { getByTestId } = render(<GenerationRecordScreen />)
        const flatList = getByTestId('generation-list')

        fireEvent(flatList, 'refresh')

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

    it('calls loadMore when reaching end of list', async () => {
        const mockGenerations = [
            {
                id: '1',
                template: { title: 'Test Template' },
                resultUrl: ['https://example.com/result.jpg'],
            },
        ]

        mockUseTemplateGenerations.mockReturnValue({
            generations: mockGenerations as any,
            loading: false,
            loadingMore: false,
            error: null,
            execute: mockExecute,
            refetch: mockRefetch,
            loadMore: mockLoadMore,
            hasMore: true,
            data: { data: mockGenerations } as any,
        })

        const { getByTestId } = render(<GenerationRecordScreen />)
        const flatList = getByTestId('generation-list')

        fireEvent(flatList, 'endReached')

        await waitFor(() => {
            expect(mockLoadMore).toHaveBeenCalledWith({ limit: 20 })
        })
    })

    it('does not call loadMore when hasMore is false', async () => {
        const mockGenerations = [
            {
                id: '1',
                template: { title: 'Test Template' },
                resultUrl: ['https://example.com/result.jpg'],
            },
        ]

        mockUseTemplateGenerations.mockReturnValue({
            generations: mockGenerations as any,
            loading: false,
            loadingMore: false,
            error: null,
            execute: mockExecute,
            refetch: mockRefetch,
            loadMore: mockLoadMore,
            hasMore: false,
            data: { data: mockGenerations } as any,
        })

        const { getByTestId } = render(<GenerationRecordScreen />)
        const flatList = getByTestId('generation-list')

        fireEvent(flatList, 'endReached')

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