import React from 'react'
import { render, screen, fireEvent, waitFor, act } from '@testing-library/react'
import { queryClient } from '../../lib/queries'
import App from '../../App'
import type { QueryResponse, IngestResponse } from '../../types'

vi.mock('../../lib/api', () => ({
  queryDocument: vi.fn(),
  ingestDocument: vi.fn(),
}))

import { queryDocument, ingestDocument } from '../../lib/api'

const mockQueryDocument = vi.mocked(queryDocument)
const mockIngestDocument = vi.mocked(ingestDocument)

const mockQueryResponse: QueryResponse = {
  keywords: ['legislative', 'council', 'meeting'],
  answer: '- The meeting was held on January 15\n- Key topics were discussed',
  sources: [
    {
      filename: 'minutes.pdf',
      upload_date: '2024-01-15',
      content_summary: 'Meeting minutes',
      chunk_index: 0,
    },
  ],
}

const mockIngestResponse: IngestResponse = {
  document_id: 'doc-abc123',
  chunk_count: 5,
  filename: 'test-document.pdf',
}

describe('Query flow integration (App-level)', () => {
  beforeEach(() => {
    queryClient.clear()
    vi.restoreAllMocks()
    mockQueryDocument.mockResolvedValue(mockQueryResponse)
    mockIngestDocument.mockResolvedValue(mockIngestResponse)
  })

  it('shows empty state initially', () => {
    render(<App />)

    expect(screen.getByText(/Video upload coming in Phase 2/i)).toBeInTheDocument()
    expect(
      screen.getByText(/Ask a question to see the answer here/i),
    ).toBeInTheDocument()

    const submitButton = screen.getByRole('button', { name: /submit/i })
    expect(submitButton).toBeDisabled()
  })

  it('full query flow: type question, submit, see keywords and answer', async () => {
    mockQueryDocument.mockResolvedValue(mockQueryResponse)

    render(<App />)

    const textarea = screen.getByPlaceholderText(
      'Ask a question about your documents...',
    )
    fireEvent.change(textarea, { target: { value: 'What happened at the meeting?' } })

    const submitButton = screen.getByRole('button', { name: /submit/i })
    await act(async () => {
      fireEvent.click(submitButton)
    })

    await waitFor(() => {
      expect(screen.getByText('legislative')).toBeInTheDocument()
    })
    expect(screen.getByText('council')).toBeInTheDocument()
    expect(screen.getByText('meeting')).toBeInTheDocument()

    await waitFor(() => {
      expect(screen.getByText('The meeting was held on January 15')).toBeInTheDocument()
    })
    expect(screen.getByText('Key topics were discussed')).toBeInTheDocument()

    expect(screen.getByText('minutes.pdf')).toBeInTheDocument()
    expect(screen.getByText('Meeting minutes')).toBeInTheDocument()
  })

  it('handles API error gracefully', async () => {
    mockQueryDocument.mockRejectedValue(new Error('Server error: 500'))

    render(<App />)

    const textarea = screen.getByPlaceholderText(
      'Ask a question about your documents...',
    )
    fireEvent.change(textarea, { target: { value: 'Will this fail?' } })

    const submitButton = screen.getByRole('button', { name: /submit/i })
    await act(async () => {
      fireEvent.click(submitButton)
    })

    await waitFor(() => {
      expect(screen.getByText(/Server error: 500/i)).toBeInTheDocument()
    })
  })

  it('handles ingest flow: upload document successfully', async () => {
    mockIngestDocument.mockResolvedValue(mockIngestResponse)

    render(<App />)

    const fileInput = screen.getByTestId('file-input')
    const file = new File(['dummy content'], 'test-document.pdf', {
      type: 'application/pdf',
    })

    await act(async () => {
      fireEvent.change(fileInput, { target: { files: [file] } })
    })

    await waitFor(() => {
      expect(screen.getByText(/Uploaded test-document\.pdf/i)).toBeInTheDocument()
    })
  })
})
