import * as React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { DeckBuilderWorkspace } from './DeckBuilderWorkspace'
import type { DeckBuilder } from './types'

/**
 * The composer is pure: it renders whatever the injected `builder` exposes and
 * lights up optional affordances (style chip, reference uploader) only when the
 * builder declares them. These tests drive it with hand-rolled builders — no app
 * import — proving the surface is app-agnostic.
 */

function makeBuilder(overrides: Partial<DeckBuilder> = {}): DeckBuilder {
  return {
    deckTitle: '',
    phase: 'empty',
    messages: [],
    slides: [],
    setActiveId: jest.fn(),
    sendMessage: jest.fn(),
    regenerate: jest.fn(),
    ...overrides,
  }
}

function renderWithClient(ui: React.ReactElement) {
  const client = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  })
  return render(<QueryClientProvider client={client}>{ui}</QueryClientProvider>)
}

describe('DeckBuilderWorkspace', () => {
  it('renders the dual-pane surface from a minimal injected builder', () => {
    renderWithClient(<DeckBuilderWorkspace builder={makeBuilder()} />)

    // Toolbar shows the placeholder title + the empty-outline hint.
    expect(screen.getByText('New presentation')).toBeInTheDocument()
    expect(screen.getByText('Paste an outline to begin')).toBeInTheDocument()

    // Empty deck pane surfaces its empty-state copy.
    expect(
      screen.getByText(/Your slides will render here as a live deck/i)
    ).toBeInTheDocument()

    // Phase-empty composer uses the outline placeholder.
    expect(
      screen.getByPlaceholderText(/Paste your outline/i)
    ).toBeInTheDocument()
  })

  it('routes composer submissions to builder.sendMessage', () => {
    const builder = makeBuilder()
    renderWithClient(<DeckBuilderWorkspace builder={builder} />)

    const textarea = screen.getByPlaceholderText(/Paste your outline/i)
    // Single-line content submits on bare Enter.
    fireEvent.change(textarea, { target: { value: 'My deck outline' } })
    fireEvent.keyDown(textarea, { key: 'Enter' })

    expect(builder.sendMessage).toHaveBeenCalledWith('My deck outline')
  })

  it('shows the derived-style chip only when the builder provides deckStyle', () => {
    const { rerender } = renderWithClient(
      <DeckBuilderWorkspace builder={makeBuilder()} />
    )
    expect(screen.queryByTestId('deck-style-chip')).not.toBeInTheDocument()

    const client = new QueryClient({ defaultOptions: { queries: { retry: false } } })
    rerender(
      <QueryClientProvider client={client}>
        <DeckBuilderWorkspace
          builder={makeBuilder({
            deckStyle: { theme: 'Modern Professional', source: 'reference' },
          })}
        />
      </QueryClientProvider>
    )
    const chip = screen.getByTestId('deck-style-chip')
    expect(chip).toBeInTheDocument()
    expect(chip).toHaveTextContent('Modern Professional')
    // `source: 'reference'` marks it as cloned.
    expect(chip).toHaveTextContent(/cloned/i)
  })

  it('wires the reference uploader only when the builder supports attachments', () => {
    // Demo-style builder: no attachments capability -> no attach affordance.
    const { unmount } = renderWithClient(
      <DeckBuilderWorkspace builder={makeBuilder()} />
    )
    expect(screen.queryByTestId('chat-attach-input')).not.toBeInTheDocument()
    unmount()

    // Backend-style builder: supportsAttachments + an injected client -> uploader on.
    const attachments = {
      listAttachments: jest.fn().mockResolvedValue([]),
      uploadAttachment: jest.fn(),
      deleteAttachment: jest.fn(),
    }
    renderWithClient(
      <DeckBuilderWorkspace
        builder={makeBuilder({
          supportsAttachments: true,
          documentId: 'doc-1',
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          attachments: attachments as any,
        })}
      />
    )
    expect(screen.getByTestId('chat-attach-input')).toBeInTheDocument()
  })
})
