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

import { AnnouncementBanner, type Announcement } from './AnnouncementBanner'

// Mock expo-linear-gradient
jest.mock('expo-linear-gradient', () => ({
  LinearGradient: ({ children, ...props }: any) => {
    const { View } = require('react-native')
    return <View {...props}>{children}</View>
  },
}))

describe('AnnouncementBanner', () => {
  const mockAnnouncements: Announcement[] = [
    {
      id: 'ann-1',
      title: '系统维护通知',
      content: '系统将于今晚进行维护',
      link: 'https://example.com/maintenance',
      createdAt: new Date('2026-01-29T10:00:00Z'),
    },
    {
      id: 'ann-2',
      title: '新功能上线',
      content: '我们推出了全新的AI生成功能',
      createdAt: new Date('2026-01-28T10:00:00Z'),
    },
    {
      id: 'ann-3',
      title: '活动公告',
      content: '春节活动即将开始',
      link: 'https://example.com/event',
      createdAt: new Date('2026-01-27T10:00:00Z'),
    },
  ]

  const mockOnPress = jest.fn()

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

  describe('Empty State', () => {
    it('should not render anything when announcements array is empty', () => {
      const { toJSON } = render(
        <AnnouncementBanner announcements={[]} onPress={mockOnPress} />
      )
      expect(toJSON()).toBeNull()
    })

    it('should not render anything when announcements is undefined', () => {
      const { toJSON } = render(
        <AnnouncementBanner announcements={undefined as any} onPress={mockOnPress} />
      )
      expect(toJSON()).toBeNull()
    })
  })

  describe('Single Announcement', () => {
    it('should render single announcement title', () => {
      const singleAnnouncement = [mockAnnouncements[0]]
      const { getByText } = render(
        <AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
      )
      expect(getByText('系统维护通知')).toBeTruthy()
    })

    it('should render announcement banner container', () => {
      const singleAnnouncement = [mockAnnouncements[0]]
      const { getByTestId } = render(
        <AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
      )
      expect(getByTestId('announcement-banner')).toBeTruthy()
    })
  })

  describe('Multiple Announcements', () => {
    it('should render multiple announcements', () => {
      const { getByText } = render(
        <AnnouncementBanner announcements={mockAnnouncements} onPress={mockOnPress} />
      )
      expect(getByText('系统维护通知')).toBeTruthy()
    })

    it('should render horizontal scroll view for multiple announcements', () => {
      const { getByTestId } = render(
        <AnnouncementBanner announcements={mockAnnouncements} onPress={mockOnPress} />
      )
      expect(getByTestId('announcement-scroll-view')).toBeTruthy()
    })

    it('should render all announcement items', () => {
      const { getAllByTestId } = render(
        <AnnouncementBanner announcements={mockAnnouncements} onPress={mockOnPress} />
      )
      const items = getAllByTestId(/^announcement-item-/)
      expect(items.length).toBe(3)
    })
  })

  describe('Press Interaction', () => {
    it('should call onPress with correct announcement when pressed', () => {
      const singleAnnouncement = [mockAnnouncements[0]]
      const { getByTestId } = render(
        <AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
      )
      fireEvent.press(getByTestId('announcement-item-ann-1'))
      expect(mockOnPress).toHaveBeenCalledTimes(1)
      expect(mockOnPress).toHaveBeenCalledWith(mockAnnouncements[0])
    })

    it('should call onPress with correct announcement for each item', () => {
      const { getByTestId } = render(
        <AnnouncementBanner announcements={mockAnnouncements} onPress={mockOnPress} />
      )

      fireEvent.press(getByTestId('announcement-item-ann-2'))
      expect(mockOnPress).toHaveBeenCalledWith(mockAnnouncements[1])
    })

    it('should not crash when onPress is not provided', () => {
      const singleAnnouncement = [mockAnnouncements[0]]
      const { getByTestId } = render(
        <AnnouncementBanner announcements={singleAnnouncement} />
      )
      expect(() => {
        fireEvent.press(getByTestId('announcement-item-ann-1'))
      }).not.toThrow()
    })
  })

  describe('Gradient Background Style', () => {
    it('should render with gradient background', () => {
      const singleAnnouncement = [mockAnnouncements[0]]
      const { getByTestId } = render(
        <AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
      )
      const banner = getByTestId('announcement-banner')
      expect(banner).toBeTruthy()
    })

    it('should apply gradient colors', () => {
      const singleAnnouncement = [mockAnnouncements[0]]
      const { getByTestId } = render(
        <AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
      )
      const gradientContainer = getByTestId('gradient-container')
      expect(gradientContainer.props.colors).toEqual(['#FF9966', '#FF6699', '#9966FF'])
    })
  })

  describe('Announcement Icon', () => {
    it('should render announcement icon', () => {
      const singleAnnouncement = [mockAnnouncements[0]]
      const { getByTestId } = render(
        <AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
      )
      expect(getByTestId('announcement-icon')).toBeTruthy()
    })
  })
})

describe('Announcement Type', () => {
  it('should have required id field', () => {
    const announcement: Announcement = {
      id: 'test-id',
      title: 'Test Title',
      createdAt: new Date(),
    }
    expect(announcement.id).toBeDefined()
  })

  it('should have required title field', () => {
    const announcement: Announcement = {
      id: 'test-id',
      title: 'Test Title',
      createdAt: new Date(),
    }
    expect(announcement.title).toBeDefined()
  })

  it('should have optional content field', () => {
    const announcement: Announcement = {
      id: 'test-id',
      title: 'Test Title',
      content: 'Test Content',
      createdAt: new Date(),
    }
    expect(announcement.content).toBe('Test Content')
  })

  it('should have optional link field', () => {
    const announcement: Announcement = {
      id: 'test-id',
      title: 'Test Title',
      link: 'https://example.com',
      createdAt: new Date(),
    }
    expect(announcement.link).toBe('https://example.com')
  })
})
