import React from 'react'
import { render, fireEvent } from '@testing-library/react-native'
import { View, Text } from 'react-native'
import VideoScreen, { VideoItem } from './video'
import type { TemplateDetail } from '@/hooks'

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

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

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

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

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

// Mock icons
jest.mock('@/components/icon', () => ({
  SameStyleIcon: 'SameStyleIcon',
  WhiteStarIcon: 'WhiteStarIcon',
}))

// Mock UI components
jest.mock('@/components/LoadingState', () => 'LoadingState')
jest.mock('@/components/ErrorState', () => 'ErrorState')
jest.mock('@/components/PaginationLoader', () => 'PaginationLoader')

// Mock react-native RefreshControl (directly from react-native)
jest.mock('react-native', () =>
    Object.assign({}, jest.requireActual('react-native'), {
        RefreshControl: 'RefreshControl',
    })
)

// Mock hooks
jest.mock('@/hooks', () => ({
  useTemplates: jest.fn(() => ({
    templates: [],
    loading: false,
    error: null,
    execute: jest.fn(),
    refetch: jest.fn(),
    loadMore: jest.fn(),
    hasMore: true,
  })),
}))

import { useRouter } from 'expo-router'
import { useTemplates } from '@/hooks'

const mockUseRouter = useRouter as jest.MockedFunction<typeof useRouter>
const mockUseTemplates = useTemplates as jest.MockedFunction<typeof useTemplates>

const createMockTemplateDetail = (overrides = {}): Partial<TemplateDetail> => ({
  id: 'template-123',
  userId: 'user-123',
  title: 'Test Template',
  titleEn: 'Test Template',
  description: 'Test description',
  descriptionEn: 'Test description',
  coverImageUrl: 'https://example.com/cover.jpg',
  previewUrl: 'https://example.com/preview.jpg',
  webpPreviewUrl: 'https://example.com/preview.webp',
  webpHighPreviewUrl: 'https://example.com/preview-high.webp',
  content: null,
  sortOrder: 0,
  viewCount: 0,
  useCount: 0,
  likeCount: 100,
  favoriteCount: 0,
  shareCount: 0,
  commentCount: 0,
  aspectRatio: '1:1',
  status: 'active',
  isDeleted: false,
  createdAt: new Date(),
  updatedAt: new Date(),
  ...overrides,
})

describe('Video Screen', () => {
  beforeEach(() => {
    jest.clearAllMocks()
  })

  describe('VideoItem Component', () => {
    const mockItem = createMockTemplateDetail() as TemplateDetail

    const mockVideoHeight = 600

    it('should render video item correctly', () => {
      const { getByText } = render(
        <VideoItem item={mockItem} videoHeight={mockVideoHeight} />
      )

      expect(getByText('Test Template')).toBeTruthy()
      expect(getByText('video.makeSame')).toBeTruthy()
    })

    it('should navigate to generateVideo with templateId when pressed', () => {
      const mockPush = jest.fn()
      mockUseRouter.mockReturnValue({ push: mockPush } as any)

      const { getByText } = render(
        <VideoItem item={mockItem} videoHeight={mockVideoHeight} />
      )

      const pressable = getByText('video.makeSame')
      fireEvent.press(pressable)

      expect(mockPush).toHaveBeenCalledWith({
        pathname: '/generateVideo',
        params: { templateId: 'template-123' },
      })
    })

    it('should prioritize webpHighPreviewUrl for display', () => {
      const itemWithWebpHigh = createMockTemplateDetail({
        webpHighPreviewUrl: 'https://example.com/high-quality.webp',
        webpPreviewUrl: 'https://example.com/normal.webp',
        previewUrl: 'https://example.com/fallback.jpg',
      }) as TemplateDetail

      const { getByText } = render(
        <VideoItem item={itemWithWebpHigh} videoHeight={mockVideoHeight} />
      )

      expect(getByText('Test Template')).toBeTruthy()
    })

    it('should fallback to webpPreviewUrl when webpHighPreviewUrl is not available', () => {
      const itemWithoutWebpHigh = createMockTemplateDetail({
        webpHighPreviewUrl: '',
        webpPreviewUrl: 'https://example.com/normal.webp',
        previewUrl: 'https://example.com/fallback.jpg',
      }) as TemplateDetail

      const { getByText } = render(
        <VideoItem item={itemWithoutWebpHigh} videoHeight={mockVideoHeight} />
      )

      expect(getByText('Test Template')).toBeTruthy()
    })

    it('should fallback to previewUrl when no webp formats are available', () => {
      const itemWithoutWebp = createMockTemplateDetail({
        webpHighPreviewUrl: '',
        webpPreviewUrl: '',
        previewUrl: 'https://example.com/fallback.jpg',
      }) as TemplateDetail

      const { getByText } = render(
        <VideoItem item={itemWithoutWebp} videoHeight={mockVideoHeight} />
      )

      expect(getByText('Test Template')).toBeTruthy()
    })

    it('should handle image load event and update imageSize state', () => {
      const { getByText } = render(
        <VideoItem item={mockItem} videoHeight={mockVideoHeight} />
      )

      expect(getByText('Test Template')).toBeTruthy()
    })

    it('should render cover image thumbnail', () => {
      const { getByText } = render(
        <VideoItem item={mockItem} videoHeight={mockVideoHeight} />
      )

      expect(getByText('Test Template')).toBeTruthy()
    })
  })

  describe('VideoScreen Component', () => {
    it('should show loading state when templates are loading', () => {
      mockUseTemplates.mockReturnValue({
        templates: [],
        loading: true,
        error: null,
        execute: jest.fn(),
        refetch: jest.fn(),
        loadMore: jest.fn(),
        hasMore: true,
      } as any)

      const { getByText } = render(<VideoScreen />)

      expect(getByText('加载中...')).toBeTruthy()
    })

    it('should show error state when templates loading fails', () => {
      mockUseTemplates.mockReturnValue({
        templates: [],
        loading: false,
        error: { message: 'Failed to load' },
        execute: jest.fn(),
        refetch: jest.fn(),
        loadMore: jest.fn(),
        hasMore: true,
      } as any)

      const { getByText } = render(<VideoScreen />)

      expect(getByText('加载失败，请下拉刷新重试')).toBeTruthy()
    })

    it('should render templates when loaded successfully', () => {
      const mockTemplates: TemplateDetail[] = [
        createMockTemplateDetail({
          id: 'template-1',
          title: 'Template 1',
          titleEn: 'Template 1',
          coverImageUrl: 'https://example.com/cover1.jpg',
          previewUrl: 'https://example.com/preview1.jpg',
        }) as TemplateDetail,
        createMockTemplateDetail({
          id: 'template-2',
          title: 'Template 2',
          titleEn: 'Template 2',
          coverImageUrl: 'https://example.com/cover2.jpg',
          previewUrl: 'https://example.com/preview2.jpg',
        }) as TemplateDetail,
      ]

      mockUseTemplates.mockReturnValue({
        templates: mockTemplates,
        loading: false,
        error: null,
        execute: jest.fn(),
        refetch: jest.fn(),
        loadMore: jest.fn(),
        hasMore: false,
      } as any)

      const { getAllByText } = render(<VideoScreen />)

      expect(getAllByText('Template 1').length).toBeGreaterThan(0)
    })

    it('should filter out video-type templates', () => {
      const mockTemplates: TemplateDetail[] = [
        createMockTemplateDetail({
          id: 'template-1',
          title: 'Image Template',
          titleEn: 'Image Template',
          coverImageUrl: 'https://example.com/cover1.jpg',
          previewUrl: 'https://example.com/preview1.jpg',
        }) as TemplateDetail,
        createMockTemplateDetail({
          id: 'template-2',
          title: 'Video Template',
          titleEn: 'Video Template',
          coverImageUrl: 'https://example.com/cover2.jpg',
          previewUrl: 'https://example.com/preview2.mp4',
        }) as TemplateDetail,
      ]

      mockUseTemplates.mockReturnValue({
        templates: mockTemplates,
        loading: false,
        error: null,
        execute: jest.fn(),
        refetch: jest.fn(),
        loadMore: jest.fn(),
        hasMore: false,
      } as any)

      const { getAllByText, queryByText } = render(<VideoScreen />)

      expect(getAllByText('Image Template').length).toBeGreaterThan(0)
      expect(queryByText('Video Template')).toBeNull()
    })

    it('should execute template fetch on mount', () => {
      const mockExecute = jest.fn()

      mockUseTemplates.mockReturnValue({
        templates: [],
        loading: false,
        error: null,
        execute: mockExecute,
        refetch: jest.fn(),
        loadMore: jest.fn(),
        hasMore: true,
      } as any)

      render(<VideoScreen />)

      expect(mockExecute).toHaveBeenCalled()
    })
  })

  describe('Helper Functions', () => {
    describe('isVideoUrl', () => {
      // Import the function for testing
      const isVideoUrl = (url: string): boolean => {
        const videoExtensions = ['.mp4', '.webm', '.mov', '.avi', '.mkv', '.m3u8']
        return videoExtensions.some(ext => url.toLowerCase().endsWith(ext))
      }

      it('should return true for .mp4 URLs', () => {
        expect(isVideoUrl('https://example.com/video.mp4')).toBe(true)
      })

      it('should return true for .webm URLs', () => {
        expect(isVideoUrl('https://example.com/video.webm')).toBe(true)
      })

      it('should return true for .mov URLs', () => {
        expect(isVideoUrl('https://example.com/video.mov')).toBe(true)
      })

      it('should return true for .avi URLs', () => {
        expect(isVideoUrl('https://example.com/video.avi')).toBe(true)
      })

      it('should return true for .mkv URLs', () => {
        expect(isVideoUrl('https://example.com/video.mkv')).toBe(true)
      })

      it('should return true for .m3u8 URLs', () => {
        expect(isVideoUrl('https://example.com/video.m3u8')).toBe(true)
      })

      it('should return false for image URLs', () => {
        expect(isVideoUrl('https://example.com/image.jpg')).toBe(false)
        expect(isVideoUrl('https://example.com/image.png')).toBe(false)
        expect(isVideoUrl('https://example.com/image.webp')).toBe(false)
      })

      it('should be case insensitive', () => {
        expect(isVideoUrl('https://example.com/video.MP4')).toBe(true)
        expect(isVideoUrl('https://example.com/video.WebM')).toBe(true)
      })
    })
  })
})
