// @vitest-environment happy-dom
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'

// Drive the per-form submissions table through a mocked forms-service so the
// test owns the data and can assert rendering, status-pill refetches, bulk
// selection, and opening the detail drawer without a real backend.
function makeEntry(over: Record<string, unknown> = {}) {
  return {
    id: 'e1',
    entryNumber: 1,
    formId: 'f1',
    data: { name: 'Jordan Avery', email: 'jordan@example.com', message: 'Hello there' },
    senderName: 'Jordan Avery',
    senderEmail: 'jordan@example.com',
    preview: 'Hello there',
    unread: true,
    starred: false,
    archived: false,
    spamStatus: 'clean',
    submittedAt: new Date().toISOString(),
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
    ...over,
  }
}

const ENTRIES = [
  makeEntry(),
  makeEntry({
    id: 'e2',
    entryNumber: 2,
    senderName: 'Priya Nair',
    senderEmail: 'priya@example.com',
    preview: 'A question about pricing',
    unread: false,
  }),
]

const fetchFormById = vi.fn(async (_id?: string) => ({
  id: 'f1',
  name: 'Contact Us',
  slug: 'contact-us',
  status: 'active',
  fields: [],
}))
const fetchEntries = vi.fn(async (_p?: unknown) => ({
  entries: ENTRIES,
  total: ENTRIES.length,
  page: 1,
  pageSize: 100,
}))
const fetchEntryCounts = vi.fn(async (_p?: unknown) => ({
  total: 2,
  unread: 1,
  starred: 0,
  thisWeek: 2,
  byForm: { f1: 1 },
}))
const fetchEntry = vi.fn(async (_id?: string) => ({ entry: ENTRIES[0], fields: [] }))
const updateEntry = vi.fn(async (_id?: string, _patch?: unknown) => ({ data: ENTRIES[0] }))

vi.mock('../../lib/forms-service.js', () => ({
  fetchFormById: (id?: string) => fetchFormById(id),
  fetchEntries: (p?: unknown) => fetchEntries(p),
  fetchEntryCounts: (p?: unknown) => fetchEntryCounts(p),
  fetchEntry: (id?: string) => fetchEntry(id),
  updateEntry: (id?: string, patch?: unknown) => updateEntry(id, patch),
  deleteEntry: vi.fn(async () => ({})),
  bulkUpdateEntries: vi.fn(async () => ({ data: { updated: 1 } })),
}))

vi.mock('../../lib/forms-events.js', () => ({
  onFormsChanged: () => () => {},
  emitFormsChanged: vi.fn(),
}))

vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn(), loading: vi.fn() } }))

const { FormSubmissions } = await import('../../views/FormSubmissions.js')

beforeEach(() => {
  fetchEntries.mockClear()
  fetchEntryCounts.mockClear()
  fetchEntry.mockClear()
})

describe('FormSubmissions table', () => {
  it('renders submissions as table rows with chips', async () => {
    render(<FormSubmissions formId="f1" onNavigate={() => {}} />)

    expect(await screen.findByText('Jordan Avery')).toBeTruthy()
    expect(screen.getByText('Priya Nair')).toBeTruthy()
    // It's a table, not cards.
    expect(screen.getByRole('table', { name: 'Submissions' })).toBeTruthy()
    // Summary chips reflect counts.
    expect(screen.getByText('this week')).toBeTruthy()
  })

  it('refetches with the unread filter when the pill is clicked', async () => {
    render(<FormSubmissions formId="f1" onNavigate={() => {}} />)
    await screen.findByText('Jordan Avery')

    fireEvent.click(screen.getByRole('button', { name: 'Unread', pressed: false }))

    await waitFor(() =>
      expect(fetchEntries).toHaveBeenCalledWith(expect.objectContaining({ unread: true })),
    )
  })

  it('shows the bulk action bar when a row is selected', async () => {
    render(<FormSubmissions formId="f1" onNavigate={() => {}} />)
    await screen.findByText('Jordan Avery')

    fireEvent.click(screen.getByLabelText('Select submission from Jordan Avery'))

    expect(await screen.findByText('1 selected')).toBeTruthy()
    expect(screen.getByRole('button', { name: 'Mark read' })).toBeTruthy()
  })

  it('opens the detail drawer when a row is clicked', async () => {
    render(<FormSubmissions formId="f1" onNavigate={() => {}} />)
    const row = await screen.findByText('Jordan Avery')

    fireEvent.click(row)

    await waitFor(() => expect(fetchEntry).toHaveBeenCalledWith('e1'))
  })
})
