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

import { MessageCard, getMessageIcon, getMessageConfig, formatRelativeTime } from './MessageCard'

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

describe('MessageCard Utilities', () => {
  describe('getMessageIcon', () => {
    it('should return celebration icon for TEMPLATE_GENERATION_SUCCESS', () => {
      expect(getMessageIcon('TEMPLATE_GENERATION_SUCCESS')).toBe('🎉')
    })

    it('should return error icon for TEMPLATE_GENERATION_FAILED', () => {
      expect(getMessageIcon('TEMPLATE_GENERATION_FAILED')).toBe('❌')
    })

    it('should return thumbs up icon for TEMPLATE_LIKED', () => {
      expect(getMessageIcon('TEMPLATE_LIKED')).toBe('👍')
    })

    it('should return star icon for TEMPLATE_FAVORITED', () => {
      expect(getMessageIcon('TEMPLATE_FAVORITED')).toBe('⭐')
    })

    it('should return comment icon for TEMPLATE_COMMENTED', () => {
      expect(getMessageIcon('TEMPLATE_COMMENTED')).toBe('💬')
    })

    it('should return comment icon for COMMENT_REPLIED', () => {
      expect(getMessageIcon('COMMENT_REPLIED')).toBe('💬')
    })

    it('should return money icon for CREDITS_DEDUCTED', () => {
      expect(getMessageIcon('CREDITS_DEDUCTED')).toBe('💰')
    })

    it('should return money icon for CREDITS_REFUNDED', () => {
      expect(getMessageIcon('CREDITS_REFUNDED')).toBe('💰')
    })

    it('should return money icon for CREDITS_RECHARGED', () => {
      expect(getMessageIcon('CREDITS_RECHARGED')).toBe('💰')
    })

    it('should return announcement icon for ANNOUNCEMENT', () => {
      expect(getMessageIcon('ANNOUNCEMENT')).toBe('📢')
    })

    it('should return default icon for unknown subType', () => {
      expect(getMessageIcon('UNKNOWN_TYPE')).toBe('📩')
    })

    it('should return default icon for undefined subType', () => {
      expect(getMessageIcon(undefined)).toBe('📩')
    })
  })

  describe('getMessageConfig', () => {
    it('should return showPreview true for TEMPLATE_GENERATION_SUCCESS', () => {
      const config = getMessageConfig('TEMPLATE_GENERATION_SUCCESS')
      expect(config.showPreview).toBe(true)
      expect(config.showAvatar).toBe(false)
    })

    it('should return showAvatar true for TEMPLATE_LIKED', () => {
      const config = getMessageConfig('TEMPLATE_LIKED')
      expect(config.showAvatar).toBe(true)
      expect(config.showPreview).toBe(false)
    })

    it('should return showAvatar true for TEMPLATE_FAVORITED', () => {
      const config = getMessageConfig('TEMPLATE_FAVORITED')
      expect(config.showAvatar).toBe(true)
    })

    it('should return showAvatar true for TEMPLATE_COMMENTED', () => {
      const config = getMessageConfig('TEMPLATE_COMMENTED')
      expect(config.showAvatar).toBe(true)
    })

    it('should return showQuote true for COMMENT_REPLIED', () => {
      const config = getMessageConfig('COMMENT_REPLIED')
      expect(config.showQuote).toBe(true)
      expect(config.showAvatar).toBe(true)
    })

    it('should return default config for unknown subType', () => {
      const config = getMessageConfig('UNKNOWN_TYPE')
      expect(config.showPreview).toBe(false)
      expect(config.showAvatar).toBe(false)
      expect(config.showQuote).toBe(false)
    })
  })

  describe('formatRelativeTime', () => {
    beforeEach(() => {
      jest.useFakeTimers()
      jest.setSystemTime(new Date('2026-01-29T12:00:00Z'))
    })

    afterEach(() => {
      jest.useRealTimers()
    })

    it('should return "刚刚" for time within 1 minute', () => {
      const now = new Date()
      const thirtySecondsAgo = new Date(now.getTime() - 30 * 1000)
      expect(formatRelativeTime(thirtySecondsAgo)).toBe('刚刚')
    })

    it('should return "X分钟前" for time within 1 hour', () => {
      const now = new Date()
      const tenMinutesAgo = new Date(now.getTime() - 10 * 60 * 1000)
      expect(formatRelativeTime(tenMinutesAgo)).toBe('10分钟前')
    })

    it('should return "X小时前" for time within 24 hours', () => {
      const now = new Date()
      const threeHoursAgo = new Date(now.getTime() - 3 * 60 * 60 * 1000)
      expect(formatRelativeTime(threeHoursAgo)).toBe('3小时前')
    })

    it('should return "昨天 HH:MM" for time within 48 hours', () => {
      const now = new Date()
      const yesterday = new Date(now.getTime() - 25 * 60 * 60 * 1000)
      const result = formatRelativeTime(yesterday)
      expect(result).toMatch(/^昨天 \d{2}:\d{2}$/)
    })

    it('should return formatted date for older times', () => {
      const now = new Date()
      const threeDaysAgo = new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000)
      const result = formatRelativeTime(threeDaysAgo)
      expect(result).toMatch(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/)
    })

    it('should handle string date input', () => {
      const result = formatRelativeTime('2026-01-29T11:50:00Z')
      expect(result).toBe('10分钟前')
    })
  })
})

describe('MessageCard Component', () => {
  const mockMessage = {
    id: 'msg-123',
    type: 'ACTIVITY' as const,
    title: '收到新点赞',
    content: '小明 赞了你的作品「风景照」',
    data: {
      subType: 'TEMPLATE_LIKED',
      likerName: '小明',
      likerAvatar: 'https://example.com/avatar.jpg',
      templateId: 'tpl-456',
      templateTitle: '风景照',
    },
    isRead: false,
    createdAt: new Date('2026-01-29T11:50:00Z'),
  }

  const mockOnPress = jest.fn()
  const mockOnDelete = jest.fn()

  beforeEach(() => {
    jest.clearAllMocks()
    jest.useFakeTimers()
    jest.setSystemTime(new Date('2026-01-29T12:00:00Z'))
  })

  afterEach(() => {
    jest.useRealTimers()
  })

  it('should render message title', () => {
    const { getByText } = render(
      <MessageCard message={mockMessage} onPress={mockOnPress} />
    )
    expect(getByText('收到新点赞')).toBeTruthy()
  })

  it('should render message content', () => {
    const { getByText } = render(
      <MessageCard message={mockMessage} onPress={mockOnPress} />
    )
    expect(getByText('小明 赞了你的作品「风景照」')).toBeTruthy()
  })

  it('should render relative time', () => {
    const { getByText } = render(
      <MessageCard message={mockMessage} onPress={mockOnPress} />
    )
    expect(getByText('10分钟前')).toBeTruthy()
  })

  it('should show unread indicator when isRead is false', () => {
    const { getByTestId } = render(
      <MessageCard message={mockMessage} onPress={mockOnPress} />
    )
    expect(getByTestId('unread-indicator')).toBeTruthy()
  })

  it('should not show unread indicator when isRead is true', () => {
    const readMessage = { ...mockMessage, isRead: true }
    const { queryByTestId } = render(
      <MessageCard message={readMessage} onPress={mockOnPress} />
    )
    expect(queryByTestId('unread-indicator')).toBeNull()
  })

  it('should call onPress when card is pressed', () => {
    const { getByTestId } = render(
      <MessageCard message={mockMessage} onPress={mockOnPress} />
    )
    fireEvent.press(getByTestId('message-card'))
    expect(mockOnPress).toHaveBeenCalledWith(mockMessage)
  })

  it('should render message icon based on subType', () => {
    const { getByText } = render(
      <MessageCard message={mockMessage} onPress={mockOnPress} />
    )
    expect(getByText('👍')).toBeTruthy()
  })

  describe('Avatar Display', () => {
    it('should show avatar for TEMPLATE_LIKED messages', () => {
      const { getByTestId } = render(
        <MessageCard message={mockMessage} onPress={mockOnPress} />
      )
      expect(getByTestId('user-avatar')).toBeTruthy()
    })

    it('should not show avatar for CREDITS_RECHARGED messages', () => {
      const billingMessage = {
        ...mockMessage,
        type: 'BILLING' as const,
        data: { subType: 'CREDITS_RECHARGED', credits: 1000 },
      }
      const { queryByTestId } = render(
        <MessageCard message={billingMessage} onPress={mockOnPress} />
      )
      expect(queryByTestId('user-avatar')).toBeNull()
    })
  })

  describe('Preview Image Display', () => {
    it('should show preview image for TEMPLATE_GENERATION_SUCCESS', () => {
      const successMessage = {
        ...mockMessage,
        type: 'SYSTEM' as const,
        data: {
          subType: 'TEMPLATE_GENERATION_SUCCESS',
          webpPreviewUrl: 'https://example.com/preview.webp',
        },
      }
      const { getByTestId } = render(
        <MessageCard message={successMessage} onPress={mockOnPress} />
      )
      expect(getByTestId('preview-image')).toBeTruthy()
    })

    it('should not show preview image when webpPreviewUrl is missing', () => {
      const successMessage = {
        ...mockMessage,
        type: 'SYSTEM' as const,
        data: { subType: 'TEMPLATE_GENERATION_SUCCESS' },
      }
      const { queryByTestId } = render(
        <MessageCard message={successMessage} onPress={mockOnPress} />
      )
      expect(queryByTestId('preview-image')).toBeNull()
    })
  })

  describe('Quote Display', () => {
    it('should show quote for COMMENT_REPLIED messages', () => {
      const replyMessage = {
        ...mockMessage,
        data: {
          subType: 'COMMENT_REPLIED',
          originalComment: '太棒了！',
          likerAvatar: 'https://example.com/avatar.jpg',
        },
      }
      const { getByTestId, getByText } = render(
        <MessageCard message={replyMessage} onPress={mockOnPress} />
      )
      expect(getByTestId('quote-container')).toBeTruthy()
      expect(getByText('太棒了！')).toBeTruthy()
    })
  })

  describe('Swipe to Delete', () => {
    it('should call onDelete when delete action is triggered', () => {
      const { getByTestId } = render(
        <MessageCard
          message={mockMessage}
          onPress={mockOnPress}
          onDelete={mockOnDelete}
        />
      )
      // Simulate swipe delete action
      const deleteButton = getByTestId('delete-button')
      fireEvent.press(deleteButton)
      expect(mockOnDelete).toHaveBeenCalledWith(mockMessage.id)
    })

    it('should not render delete button when onDelete is not provided', () => {
      const { queryByTestId } = render(
        <MessageCard message={mockMessage} onPress={mockOnPress} />
      )
      expect(queryByTestId('delete-button')).toBeNull()
    })
  })
})

describe('MessageCard Types', () => {
  it('should accept Message type with all required fields', () => {
    const message = {
      id: 'msg-123',
      type: 'SYSTEM' as const,
      title: 'Test Title',
      content: 'Test Content',
      isRead: false,
      createdAt: new Date(),
    }
    expect(message.id).toBeDefined()
    expect(message.type).toBeDefined()
    expect(message.title).toBeDefined()
    expect(message.content).toBeDefined()
    expect(message.isRead).toBeDefined()
    expect(message.createdAt).toBeDefined()
  })

  it('should accept Message type with optional data field', () => {
    const message = {
      id: 'msg-123',
      type: 'ACTIVITY' as const,
      title: 'Test Title',
      content: 'Test Content',
      data: {
        subType: 'TEMPLATE_LIKED',
        likerName: '小明',
      },
      isRead: false,
      createdAt: new Date(),
    }
    expect(message.data).toBeDefined()
    expect(message.data?.subType).toBe('TEMPLATE_LIKED')
  })

  it('should handle all message types', () => {
    const types = ['SYSTEM', 'ACTIVITY', 'BILLING', 'MARKETING'] as const
    types.forEach((type) => {
      const message = {
        id: 'msg-123',
        type,
        title: 'Test',
        content: 'Test',
        isRead: false,
        createdAt: new Date(),
      }
      expect(message.type).toBe(type)
    })
  })
})
