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

// Drive the dashboard purely through `useApiData`. Each endpoint's result
// is looked up in `responses`, so tests can set just the data they care
// about and everything else falls back to a benign empty state.
const responses: Record<string, unknown> = {}
const emptyResult = { data: null, loading: false, error: null, exhausted: false, refetch: () => {} }

vi.mock('../../lib/useApiData.js', () => ({
  useApiData: (endpoint: string | null) => responses[endpoint ?? ''] ?? emptyResult,
}))

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

const emptyStats = {
  totalDocuments: 0,
  totalMedia: 0,
  totalUsers: 0,
  formCount: 0,
  avgSeoScore: 0,
  webhookCount: 0,
  webhookActiveCount: 0,
  collectionCounts: {},
  statusCounts: {},
  recentDocuments: [] as unknown[],
}

function statsResult(over: Partial<typeof emptyStats> = {}) {
  return {
    data: { ...emptyStats, ...over },
    loading: false,
    error: null,
    exhausted: false,
    refetch: () => {},
  }
}

beforeEach(() => {
  for (const k of Object.keys(responses)) delete responses[k]
})

describe('Dashboard', () => {
  it('renders a spinner while the primary stats request is still loading', () => {
    responses['/stats'] = {
      data: null,
      loading: true,
      error: null,
      exhausted: false,
      refetch: () => {},
    }

    const { container } = render(
      <Dashboard config={{ collections: [] }} session={{}} onNavigate={() => {}} />,
    )

    expect(container.querySelector('.animate-spin')).toBeTruthy()
    expect(screen.queryByText('Recent Activity')).toBeNull()
  })

  it('shows empty states when there is no content', () => {
    responses['/stats'] = statsResult()

    render(<Dashboard config={{ collections: [] }} session={{}} onNavigate={() => {}} />)

    expect(screen.getByText('No activity yet')).toBeTruthy()
    expect(screen.getByText('No scheduled content')).toBeTruthy()
  })

  it('surfaces a retryable banner when the stats request is exhausted', () => {
    const refetch = vi.fn()
    responses['/stats'] = { data: null, loading: false, error: 'down', exhausted: true, refetch }

    render(<Dashboard config={{ collections: [] }} session={{}} onNavigate={() => {}} />)

    fireEvent.click(screen.getByText('Retry'))
    expect(refetch).toHaveBeenCalledTimes(1)
  })

  // ── EI-1 regression: recent-activity rows must open the *correct* editor ──

  it('routes a recent post to the section-based post editor (not the legacy editor)', () => {
    const onNavigate = vi.fn()
    responses['/stats'] = statsResult({
      recentDocuments: [
        {
          id: 'p1',
          title: 'My Post',
          status: 'DRAFT',
          collection: 'blog',
          updatedAt: new Date().toISOString(),
          author: 'Sam',
        },
      ],
    })

    render(
      <Dashboard
        config={{
          collections: [
            { slug: 'blog', type: 'post', labels: { singular: 'Blog', plural: 'Blogs' } },
          ],
        }}
        session={{}}
        onNavigate={onNavigate}
      />,
    )

    // EI-2: the row is an accessible button, so it is reachable by role.
    fireEvent.click(screen.getByRole('button', { name: /My Post/ }))
    expect(onNavigate).toHaveBeenCalledWith('/posts/blog/p1/edit')
  })

  it('routes a recent page to the full page editor', () => {
    const onNavigate = vi.fn()
    responses['/stats'] = statsResult({
      recentDocuments: [
        {
          id: 'pg1',
          title: 'Home',
          status: 'PUBLISHED',
          collection: 'pages',
          updatedAt: new Date().toISOString(),
          author: 'Sam',
        },
      ],
    })

    render(
      <Dashboard
        config={{
          collections: [
            { slug: 'pages', type: 'page', labels: { singular: 'Page', plural: 'Pages' } },
          ],
        }}
        session={{}}
        onNavigate={onNavigate}
      />,
    )

    fireEvent.click(screen.getByRole('button', { name: /Home/ }))
    expect(onNavigate).toHaveBeenCalledWith('/pages/pg1/edit')
  })

  it('routes a scheduled queue item through the same editor resolver', () => {
    const onNavigate = vi.fn()
    responses['/stats'] = statsResult({
      recentDocuments: [
        {
          id: 'p9',
          title: 'Scheduled Post',
          status: 'SCHEDULED',
          collection: 'blog',
          updatedAt: new Date().toISOString(),
          author: 'Sam',
        },
      ],
    })

    render(
      <Dashboard
        config={{
          collections: [
            { slug: 'blog', type: 'post', labels: { singular: 'Blog', plural: 'Blogs' } },
          ],
        }}
        session={{}}
        onNavigate={onNavigate}
      />,
    )

    // The publishing-queue row (right column) — there are two buttons named
    // for the post (activity + queue); the queue "Manage" header button also
    // targets the first scheduled item. Click the queue row directly.
    const queueButtons = screen.getAllByRole('button', { name: /Scheduled Post/ })
    fireEvent.click(queueButtons[queueButtons.length - 1]!)
    expect(onNavigate).toHaveBeenCalledWith('/posts/blog/p9/edit')
  })
})
