import React from 'react'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, waitFor } from '@testing-library/react'
import { MemoryRouter, Routes, Route } from 'react-router-dom'

let mockItems = []
let mockViewer = null
vi.mock('../api', () => ({
  listCollections: vi.fn(async () => ({ items: mockItems, viewer: mockViewer })),
  // JoinRequestModal (rendered behind the affordance) pulls these in.
  joinTarget: vi.fn(async () => ({ eligible: true, name: 'Ohm', already_requested: false })),
  requestJoin: vi.fn(async () => ({ status: 'pending' })),
}))
import CollectionDirectory from './CollectionDirectory.jsx'

beforeEach(() => { mockItems = []; mockViewer = null })

function renderDir(items, viewer = null) {
  mockItems = items
  mockViewer = viewer
  return render(
    <MemoryRouter initialEntries={["/p/ohm/"]}>
      <Routes>
        <Route path="/p/:projectId/*" element={<CollectionDirectory projectId="ohm" />} />
        <Route path="/p/:projectId/c/:collectionId/*" element={<div>collection home</div>} />
      </Routes>
    </MemoryRouter>,
  )
}

describe('CollectionDirectory', () => {
  it('lists a card per collection with the type-driven noun + link when 2+', async () => {
    renderDir([
      { id: 'default', name: 'Model', type: 'document' },
      { id: 'features', name: 'Scenarios', type: 'bdd' },
    ])
    await waitFor(() => expect(screen.getByText('Scenarios')).toBeInTheDocument())
    expect(screen.getByText('Model').closest('a')).toHaveAttribute('href', '/p/ohm/c/default/')
    expect(screen.getByText('Scenarios').closest('a')).toHaveAttribute('href', '/p/ohm/c/features/')
    expect(screen.getByText('RFCs')).toBeInTheDocument()       // document → RFCs
    expect(screen.getByText('Features')).toBeInTheDocument()   // bdd → Features (type noun)
  })

  it('redirects into the sole collection when exactly one is visible', async () => {
    renderDir([{ id: 'default', name: 'Model', type: 'document' }])
    await waitFor(() => expect(screen.getByText('collection home')).toBeInTheDocument())
  })

  it('shows a minimal empty note when there are no collections', async () => {
    renderDir([])
    await waitFor(() => expect(screen.getByText('No collections yet.')).toBeInTheDocument())
  })

  it('offers "Request to join" when the viewer holds no role (§22.8)', async () => {
    renderDir(
      [
        { id: 'a', name: 'A', type: 'document' },
        { id: 'b', name: 'B', type: 'document' },
      ],
      { can_request_join: true },
    )
    await waitFor(() => expect(screen.getByText('Request to join')).toBeInTheDocument())
  })

  it('hides "Request to join" from a member', async () => {
    renderDir(
      [
        { id: 'a', name: 'A', type: 'document' },
        { id: 'b', name: 'B', type: 'document' },
      ],
      { role: 'owner', can_request_join: false },
    )
    await waitFor(() => expect(screen.getByText('A')).toBeInTheDocument())
    expect(screen.queryByText('Request to join')).not.toBeInTheDocument()
  })
})
