import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte'
import DeckReviews from './DeckReviews.svelte'

const mockPush = vi.fn()
vi.mock('svelte-spa-router', () => ({
  push: (...args) => mockPush(...args),
}))

const mockFetchDeckWithQuestions = vi.fn()
const mockGetDeckReviews = vi.fn()
vi.mock('../lib/api/decks.js', () => ({
  fetchDeckWithQuestions: (...args) => mockFetchDeckWithQuestions(...args),
  getDeckReviews: (...args) => mockGetDeckReviews(...args),
}))

describe('DeckReviews', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockFetchDeckWithQuestions.mockResolvedValue({
      id: 'd1',
      title: 'Test Deck',
      published: true,
      questions: [],
    })
    mockGetDeckReviews.mockResolvedValue([])
  })

  it('shows loading then deck title and no reviews', async () => {
    render(DeckReviews, { props: { params: { id: 'd1' } } })
    expect(screen.getByText('Loading…')).toBeInTheDocument()
    await waitFor(() => expect(screen.getByText('Test Deck')).toBeInTheDocument())
    expect(screen.getByText('No reviews yet.')).toBeInTheDocument()
    expect(mockFetchDeckWithQuestions).toHaveBeenCalledWith(expect.anything(), 'd1')
    expect(mockGetDeckReviews).toHaveBeenCalledWith(expect.anything(), 'd1')
  })

  it('shows error when deck fetch fails', async () => {
    mockFetchDeckWithQuestions.mockRejectedValue(new Error('Network error'))
    render(DeckReviews, { props: { params: { id: 'd1' } } })
    await waitFor(() => expect(screen.getByText('Network error')).toBeInTheDocument())
  })

  it('shows error when deck is not published', async () => {
    mockFetchDeckWithQuestions.mockResolvedValue({
      id: 'd1',
      title: 'Private',
      published: false,
      questions: [],
    })
    render(DeckReviews, { props: { params: { id: 'd1' } } })
    await waitFor(() => expect(screen.getByText('This deck is not available.')).toBeInTheDocument())
  })

  it('renders reviews list and goBack calls push', async () => {
    mockGetDeckReviews.mockResolvedValue([
      {
        user_id: 'u1',
        rating: 5,
        comment: 'Great!',
        display_name: 'Alice',
        email: 'a@b.com',
        avatar_url: null,
      },
    ])
    render(DeckReviews, { props: { params: { id: 'd1' } } })
    await waitFor(() => expect(screen.getByText('Alice')).toBeInTheDocument())
    expect(screen.getByText('Great!')).toBeInTheDocument()
    await fireEvent.click(screen.getByRole('button', { name: /Back to deck/i }))
    expect(mockPush).toHaveBeenCalledWith('/decks/d1/preview')
  })
})
