import { describe, it, expect } from 'vitest'
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react-native'
import { CollectionCard } from '@/src/shared/components/CollectionCard'
import type { Collection } from '@/src/shared/types'

const mockCollection: Collection = {
  id: 'test-collection',
  title: 'Upper Body Blast',
  description: 'An intense upper body workout collection',
  icon: '💪',
  workoutIds: ['w1', 'w2', 'w3'],
  gradient: ['#FF6B35', '#FF3B30'],
}

/**
 * Helper to recursively find a node in the rendered tree by type.
 */
function findByType(tree: any, typeName: string): any {
  if (!tree) return null
  if (tree.type === typeName) return tree
  if (tree.children && Array.isArray(tree.children)) {
    for (const child of tree.children) {
      if (typeof child === 'object') {
        const found = findByType(child, typeName)
        if (found) return found
      }
    }
  }
  return null
}

describe('CollectionCard', () => {
  it('renders collection title', () => {
    render(<CollectionCard collection={mockCollection} />)
    expect(screen.getByText('Upper Body Blast')).toBeTruthy()
  })

  it('renders workout count', () => {
    render(<CollectionCard collection={mockCollection} />)
    expect(screen.getByText('3 workouts')).toBeTruthy()
  })

  it('renders icon emoji', () => {
    render(<CollectionCard collection={mockCollection} />)
    expect(screen.getByText('💪')).toBeTruthy()
  })

  it('calls onPress when pressed', () => {
    const onPress = vi.fn()
    render(<CollectionCard collection={mockCollection} onPress={onPress} />)
    fireEvent.press(screen.getByText('Upper Body Blast'))
    expect(onPress).toHaveBeenCalledTimes(1)
  })

  it('renders without onPress (no crash)', () => {
    const { toJSON } = render(<CollectionCard collection={mockCollection} />)
    expect(toJSON()).toMatchSnapshot()
  })

  it('renders LinearGradient when no imageUrl', () => {
    const { toJSON } = render(<CollectionCard collection={mockCollection} />)
    expect(screen.getByTestId('linear-gradient')).toBeTruthy()
    // LinearGradient should receive the collection's gradient colors
    const gradientNode = findByType(toJSON(), 'LinearGradient')
    expect(gradientNode).toBeTruthy()
    expect(gradientNode.props.colors).toEqual(['#FF6B35', '#FF3B30'])
  })

  it('renders ImageBackground when imageUrl is provided', () => {
    const { toJSON } = render(
      <CollectionCard
        collection={mockCollection}
        imageUrl="https://example.com/image.jpg"
      />
    )
    // Should render ImageBackground instead of standalone LinearGradient
    const tree = toJSON()
    const imageBackground = findByType(tree, 'ImageBackground')
    expect(imageBackground).toBeTruthy()
    expect(imageBackground.props.source).toEqual({ uri: 'https://example.com/image.jpg' })
  })

  it('uses default gradient colors when collection has no gradient', () => {
    const collectionNoGradient: Collection = {
      ...mockCollection,
      gradient: undefined,
    }
    const { toJSON } = render(
      <CollectionCard collection={collectionNoGradient} />
    )
    // Should use fallback gradient: [BRAND.PRIMARY, '#FF3B30']
    const gradientNode = findByType(toJSON(), 'LinearGradient')
    expect(gradientNode).toBeTruthy()
    // BRAND.PRIMARY = '#FF6B35' from constants
    expect(gradientNode.props.colors).toEqual(['#FF6B35', '#FF3B30'])
  })

  it('renders blur overlay', () => {
    render(<CollectionCard collection={mockCollection} />)
    expect(screen.getByTestId('blur-view')).toBeTruthy()
  })

  it('handles empty workoutIds', () => {
    const emptyCollection: Collection = {
      ...mockCollection,
      workoutIds: [],
    }
    render(<CollectionCard collection={emptyCollection} />)
    expect(screen.getByText('0 workouts')).toBeTruthy()
  })

  it('snapshot with imageUrl (different rendering path)', () => {
    const { toJSON } = render(
      <CollectionCard
        collection={mockCollection}
        imageUrl="https://example.com/image.jpg"
      />
    )
    expect(toJSON()).toMatchSnapshot()
  })
})
