import { describe, it, expect, vi, beforeEach } from 'vitest'
import React from 'react'
import { render, screen, fireEvent, act } from '@testing-library/react-native'
import { SyncConsentModal } from '@/src/shared/components/SyncConsentModal'

describe('SyncConsentModal', () => {
  const defaultProps = {
    visible: true,
    onAccept: vi.fn().mockResolvedValue(undefined),
    onDecline: vi.fn(),
  }

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

  it('renders when visible is true', () => {
    render(<SyncConsentModal {...defaultProps} />)
    expect(screen.getByText('sync.title')).toBeTruthy()
  })

  it('renders sparkles icon', () => {
    render(<SyncConsentModal {...defaultProps} />)
    expect(screen.getByTestId('icon-sparkles')).toBeTruthy()
  })

  it('renders benefit rows', () => {
    render(<SyncConsentModal {...defaultProps} />)
    expect(screen.getByText('sync.benefits.recommendations')).toBeTruthy()
    expect(screen.getByText('sync.benefits.adaptive')).toBeTruthy()
    expect(screen.getByText('sync.benefits.sync')).toBeTruthy()
    expect(screen.getByText('sync.benefits.secure')).toBeTruthy()
  })

  it('renders benefit icons', () => {
    render(<SyncConsentModal {...defaultProps} />)
    expect(screen.getByTestId('icon-trending-up')).toBeTruthy()
    expect(screen.getByTestId('icon-fitness')).toBeTruthy()
    expect(screen.getByTestId('icon-sync')).toBeTruthy()
    expect(screen.getByTestId('icon-shield-checkmark')).toBeTruthy()
  })

  it('renders privacy note', () => {
    render(<SyncConsentModal {...defaultProps} />)
    expect(screen.getByText('sync.privacy')).toBeTruthy()
  })

  it('renders primary and secondary buttons', () => {
    render(<SyncConsentModal {...defaultProps} />)
    expect(screen.getByText('sync.primaryButton')).toBeTruthy()
    expect(screen.getByText('sync.secondaryButton')).toBeTruthy()
  })

  it('calls onDecline when secondary button is pressed', () => {
    render(<SyncConsentModal {...defaultProps} />)
    fireEvent.press(screen.getByText('sync.secondaryButton'))
    expect(defaultProps.onDecline).toHaveBeenCalledTimes(1)
  })

  it('calls onAccept when primary button is pressed', async () => {
    render(<SyncConsentModal {...defaultProps} />)
    await act(async () => {
      fireEvent.press(screen.getByText('sync.primaryButton'))
    })
    expect(defaultProps.onAccept).toHaveBeenCalledTimes(1)
  })

  it('shows loading text while accepting', async () => {
    let resolveAccept: () => void
    const slowAccept = new Promise<void>((resolve) => {
      resolveAccept = resolve
    })
    const onAccept = vi.fn(() => slowAccept)

    render(<SyncConsentModal visible={true} onAccept={onAccept} onDecline={vi.fn()} />)

    await act(async () => {
      fireEvent.press(screen.getByText('sync.primaryButton'))
    })

    expect(screen.getByText('Setting up...')).toBeTruthy()

    await act(async () => {
      resolveAccept!()
    })
  })

  it('does not render content when visible is false', () => {
    render(<SyncConsentModal {...defaultProps} visible={false} />)
    expect(screen.queryByText('sync.title')).toBeNull()
  })

  it('full modal structure snapshot', () => {
    const { toJSON } = render(<SyncConsentModal {...defaultProps} />)
    expect(toJSON()).toMatchSnapshot()
  })

  it('primary button shows disabled state while loading', async () => {
    let resolveAccept: () => void
    const slowAccept = new Promise<void>((resolve) => {
      resolveAccept = resolve
    })
    const onAccept = vi.fn(() => slowAccept)

    const { toJSON } = render(
      <SyncConsentModal visible={true} onAccept={onAccept} onDecline={vi.fn()} />
    )

    await act(async () => {
      fireEvent.press(screen.getByText('sync.primaryButton'))
    })

    // While loading, button text changes to loading state
    expect(screen.getByText('Setting up...')).toBeTruthy()

    // Verify the tree has the disabled styling applied (opacity: 0.6)
    const tree = toJSON()
    const treeStr = JSON.stringify(tree)
    expect(treeStr).toContain('"opacity":0.6')

    await act(async () => {
      resolveAccept!()
    })
  })
})
