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

// Drive the Forms list through a mocked forms-service so the test owns the
// data and can assert filtering, search, the notify toggle, and the schema
// drawer without a real backend.
function makeForm(over: Record<string, unknown> = {}) {
  return {
    id: 'f1',
    name: 'Contact Us',
    slug: 'contact-us',
    description: 'General contact and inquiries',
    status: 'active',
    fields: [
      { id: 'c1', label: 'Full Name', key: 'name', type: 'text', required: true, sortOrder: 0 },
      { id: 'c2', label: 'Email', key: 'email', type: 'email', required: true, sortOrder: 1 },
    ],
    fieldCount: 2,
    totalEntries: 47,
    unreadEntries: 8,
    submissions: 47,
    notifyEnabled: true,
    lastEntryAt: new Date().toISOString(),
    ...over,
  }
}

const FORMS = [
  makeForm(),
  makeForm({
    id: 'f2',
    name: 'Event RSVP',
    slug: 'event-rsvp',
    description: 'Webinar registration',
    status: 'draft',
    totalEntries: 0,
    unreadEntries: 0,
    notifyEnabled: false,
    lastEntryAt: null,
  }),
]

const fetchForms = vi.fn(async () => FORMS)
const fetchFormStats = vi.fn(async () => ({
  totalForms: 2,
  activeForms: 1,
  totalEntries: 47,
  unreadEntries: 8,
}))
const setNotifyEnabled = vi.fn(async (_id: string, _v: boolean) => ({
  data: { notifyEnabled: false },
}))
const fetchFormSchema = vi.fn(async () => ({
  fields: FORMS[0]!.fields,
  activeVersionId: null,
  versions: [],
}))
const fetchEmbedSettings = vi.fn(async () => ({}))
const fetchNotificationSettings = vi.fn(async () => ({ enabled: true, recipients: [] }))

vi.mock('../../lib/forms-service.js', () => ({
  fetchForms: () => fetchForms(),
  fetchFormStats: () => fetchFormStats(),
  setNotifyEnabled: (id: string, v: boolean) => setNotifyEnabled(id, v),
  fetchFormSchema: () => fetchFormSchema(),
  saveFormSchema: vi.fn(async () => ({ data: {} })),
  fetchEmbedSettings: () => fetchEmbedSettings(),
  updateEmbedSettings: vi.fn(async () => ({ data: {} })),
  fetchNotificationSettings: () => fetchNotificationSettings(),
  updateNotificationSettings: vi.fn(async () => ({ data: {} })),
}))

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

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

beforeEach(() => {
  fetchForms.mockClear()
  fetchFormStats.mockClear()
  setNotifyEnabled.mockClear()
})

describe('Forms list', () => {
  it('renders forms, summary chips, and field badges from service data', async () => {
    render(<Forms onNavigate={() => {}} />)

    expect(await screen.findByText('Contact Us')).toBeTruthy()
    expect(screen.getByText('Event RSVP')).toBeTruthy()
    // Summary chips reflect stats (not hardcoded).
    expect(screen.getByText('total entries')).toBeTruthy()
    // Field-type badges render per form.
    expect(screen.getAllByText('EMAIL').length).toBeGreaterThan(0)
  })

  it('filters by status pill', async () => {
    render(<Forms onNavigate={() => {}} />)
    await screen.findByText('Contact Us')

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

    // Active-only form is filtered out; the draft remains.
    await waitFor(() => {
      expect(screen.queryByText('Contact Us')).toBeNull()
      expect(screen.getByText('Event RSVP')).toBeTruthy()
    })
  })

  it('searches across name and field labels', async () => {
    render(<Forms onNavigate={() => {}} />)
    await screen.findByText('Contact Us')

    fireEvent.change(screen.getByLabelText('Search forms'), { target: { value: 'rsvp' } })

    await waitFor(() => {
      expect(screen.getByText('Event RSVP')).toBeTruthy()
      expect(screen.queryByText('Contact Us')).toBeNull()
    })
  })

  it('optimistically persists the notify toggle', async () => {
    render(<Forms onNavigate={() => {}} />)
    await screen.findByText('Contact Us')

    const toggles = screen.getAllByLabelText(/Notifications for/)
    fireEvent.click(toggles[0]!)

    await waitFor(() => expect(setNotifyEnabled).toHaveBeenCalledWith('f1', false))
  })

  it('opens the schema drawer from the Schema action', async () => {
    render(<Forms onNavigate={() => {}} />)
    await screen.findByText('Contact Us')

    fireEvent.click(screen.getAllByRole('button', { name: 'Schema' })[0]!)

    await waitFor(() => expect(fetchFormSchema).toHaveBeenCalled())
    // Drawer tabs are present.
    expect(await screen.findByRole('tab', { name: 'Fields' })).toBeTruthy()
  })
})
