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

// Keep the pure shaping helpers (applyPagesQuery/groupPages) real — the
// list view relies on them for in-memory filtering — and stub only the
// network read + bulk mutations.
const fetchPagesDataset = vi.fn()
vi.mock('../../lib/pages-service.js', async (importOriginal) => {
  const actual = await importOriginal<typeof import('../../lib/pages-service.js')>()
  return {
    ...actual,
    fetchPagesDataset: () => fetchPagesDataset(),
  }
})

const { PagesListView } = await import('../../views/Pages/PagesListView.js')
import type { Page, PageTag, PagesDataset } from '../../lib/pages-service.js'

afterEach(() => {
  fetchPagesDataset.mockReset()
})

function page(id: string, over: Partial<Page> = {}): Page {
  return {
    id,
    title: id,
    path: `/${id}`,
    slug: id,
    parentPageId: null,
    tags: [],
    primaryTagId: null,
    authorId: 'u1',
    authorName: 'Jane Doe',
    authorInitials: 'JD',
    status: 'PUBLISHED',
    publishDate: null,
    scheduledDate: null,
    lastModified: '2026-01-01T00:00:00Z',
    seoScore: 80,
    seoTitle: null,
    seoDescription: null,
    templateId: null,
    isHomepage: false,
    isSystemPage: false,
    createdAt: '2026-01-01T00:00:00Z',
    updatedAt: '2026-01-01T00:00:00Z',
    ...over,
  }
}

function tag(slug: string, pageCount: number): PageTag {
  return {
    id: slug,
    docId: `doc-${slug}`,
    name: slug.toUpperCase(),
    slug,
    description: null,
    color: 'green',
    pageCount,
    sortOrder: 0,
    active: true,
    createdAt: null,
    updatedAt: null,
  }
}

function dataset(over: Partial<PagesDataset> = {}): PagesDataset {
  return { pages: [], tags: [], authors: [], ...over }
}

describe('PagesListView', () => {
  it('counts untagged pages in the grand total (I-1 regression)', async () => {
    // Two pages tagged "a", one untagged. A tag-sum total would report 2;
    // the grand total must be 3.
    fetchPagesDataset.mockResolvedValue(
      dataset({
        pages: [
          page('p1', { tags: ['a'], primaryTagId: 'a' }),
          page('p2', { tags: ['a'], primaryTagId: 'a' }),
          page('p3'),
        ],
        tags: [tag('a', 2)],
      }),
    )

    render(<PagesListView onNavigate={() => {}} />)

    expect(await screen.findByText(/3 pages · organized by tags/)).toBeTruthy()
    expect(screen.getByText('3 of 3')).toBeTruthy()
  })

  it('renders the empty state when there are no pages', async () => {
    fetchPagesDataset.mockResolvedValue(dataset())
    render(<PagesListView onNavigate={() => {}} />)
    expect(await screen.findByText('No pages yet')).toBeTruthy()
  })

  it('shows an error with a retry that refetches', async () => {
    fetchPagesDataset.mockRejectedValueOnce(new Error('Boom'))
    render(<PagesListView onNavigate={() => {}} />)

    expect(await screen.findByText('Boom')).toBeTruthy()

    fetchPagesDataset.mockResolvedValueOnce(dataset({ pages: [page('p1')] }))
    fireEvent.click(screen.getByText('Try again'))

    await waitFor(() => expect(screen.getByText('1 of 1')).toBeTruthy())
  })

  it('navigates to the section editor when a row is opened', async () => {
    const onNavigate = vi.fn()
    fetchPagesDataset.mockResolvedValue(dataset({ pages: [page('about', { title: 'About' })] }))
    render(<PagesListView onNavigate={onNavigate} />)

    fireEvent.click(await screen.findByText('About'))
    expect(onNavigate).toHaveBeenCalledWith('/pages/about/edit')
  })
})
