import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import {
  ApolloEnrichButton,
  type ApolloEnrichmentClient,
  type ApolloEnrichmentSummary,
} from '../ApolloEnrichButton'

function makeClient(
  resolveWith: ApolloEnrichmentSummary | Promise<ApolloEnrichmentSummary> = {
    total: 0,
    enriched: [],
    skipped: [],
    errors: [],
    missing: [],
  },
): ApolloEnrichmentClient & { enrichApollo: jest.Mock } {
  const enrichApollo = jest
    .fn()
    .mockReturnValue(
      resolveWith instanceof Promise ? resolveWith : Promise.resolve(resolveWith),
    )
  return { enrichApollo }
}


describe('ApolloEnrichButton', () => {
  it('renders the button label and contact count', () => {
    const client = makeClient()
    render(
      <ApolloEnrichButton contactIds={['c-1', 'c-2', 'c-3']} enrichmentApi={client} />,
    )
    expect(screen.getByText(/Enrich with Apollo/i)).toBeInTheDocument()
    expect(screen.getByText('(3)')).toBeInTheDocument()
  })

  it('disables the button when no contactIds', () => {
    const client = makeClient()
    render(<ApolloEnrichButton contactIds={[]} enrichmentApi={client} />)
    const btn = screen.getByRole('button', { name: /Enrich with Apollo/i })
    expect(btn).toBeDisabled()
  })

  it('disables the button when disabled=true', () => {
    const client = makeClient()
    render(
      <ApolloEnrichButton contactIds={['c-1']} enrichmentApi={client} disabled />,
    )
    expect(screen.getByRole('button', { name: /Enrich with Apollo/i })).toBeDisabled()
  })

  it('opens dialog and calls enrichApollo with contactIds on click', async () => {
    const summary: ApolloEnrichmentSummary = {
      total: 2,
      enriched: ['c-1', 'c-2'],
      skipped: [],
      errors: [],
      missing: [],
    }
    const client = makeClient(summary)
    render(
      <ApolloEnrichButton contactIds={['c-1', 'c-2']} enrichmentApi={client} />,
    )
    fireEvent.click(screen.getByRole('button', { name: /Enrich with Apollo/i }))

    expect(client.enrichApollo).toHaveBeenCalledWith(['c-1', 'c-2'])

    await waitFor(() => {
      expect(screen.getByText(/Apollo enrichment complete/i)).toBeInTheDocument()
    })
  })

  it('shows skipped reasons in the summary', async () => {
    const summary: ApolloEnrichmentSummary = {
      total: 1,
      enriched: [],
      skipped: [{ contact_id: 'c-1', reason: 'insufficient query fields' }],
      errors: [],
      missing: [],
    }
    const client = makeClient(summary)
    render(<ApolloEnrichButton contactIds={['c-1']} enrichmentApi={client} />)
    fireEvent.click(screen.getByRole('button', { name: /Enrich with Apollo/i }))

    await waitFor(() => {
      expect(screen.getByText(/Skipped reasons/i)).toBeInTheDocument()
      expect(screen.getByText(/insufficient query fields/i)).toBeInTheDocument()
    })
  })

  it('shows errors in the summary', async () => {
    const summary: ApolloEnrichmentSummary = {
      total: 1,
      enriched: [],
      skipped: [],
      errors: [{ contact_id: 'c-1', error: 'Apollo error: 401' }],
      missing: [],
    }
    const client = makeClient(summary)
    render(<ApolloEnrichButton contactIds={['c-1']} enrichmentApi={client} />)
    fireEvent.click(screen.getByRole('button', { name: /Enrich with Apollo/i }))

    await waitFor(() => {
      expect(screen.getByText(/Errored/i)).toBeInTheDocument()
      expect(screen.getByText(/Apollo error: 401/i)).toBeInTheDocument()
    })
  })

  it('shows error alert when API call rejects', async () => {
    const client = makeClient(Promise.reject(new Error('network down')))
    render(<ApolloEnrichButton contactIds={['c-1']} enrichmentApi={client} />)
    fireEvent.click(screen.getByRole('button', { name: /Enrich with Apollo/i }))

    await waitFor(() => {
      expect(screen.getByRole('alert')).toHaveTextContent(/network down/i)
    })
  })

  it('calls onComplete with the summary', async () => {
    const summary: ApolloEnrichmentSummary = {
      total: 1,
      enriched: ['c-1'],
      skipped: [],
      errors: [],
      missing: [],
    }
    const client = makeClient(summary)
    const onComplete = jest.fn()
    render(
      <ApolloEnrichButton
        contactIds={['c-1']}
        enrichmentApi={client}
        onComplete={onComplete}
      />,
    )
    fireEvent.click(screen.getByRole('button', { name: /Enrich with Apollo/i }))

    await waitFor(() => {
      expect(onComplete).toHaveBeenCalledWith(summary)
    })
  })

  it('honors a custom label', () => {
    const client = makeClient()
    render(
      <ApolloEnrichButton
        contactIds={['c-1']}
        enrichmentApi={client}
        label="Custom Label"
      />,
    )
    expect(screen.getByRole('button', { name: /Custom Label/i })).toBeInTheDocument()
  })
})
