import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte'
import EditDeck from './EditDeck.svelte'
import { auth } from '../lib/stores/auth.js'

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

vi.mock('../lib/stores/auth.js', () => {
  const { writable } = require('svelte/store')
  const store = writable({ user: { id: 'u1' }, loading: false, error: null })
  return { auth: { subscribe: store.subscribe, set: store.set } }
})

const mockFetchDeckWithQuestions = vi.fn()
const mockUpdateDeck = vi.fn()
vi.mock('../lib/api/decks.js', () => ({
  fetchDeckWithQuestions: (...args) => mockFetchDeckWithQuestions(...args),
  updateDeck: (...args) => mockUpdateDeck(...args),
  togglePublished: vi.fn(),
  deleteDeck: vi.fn(),
}))

describe('EditDeck', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    auth.set({ user: { id: 'u1' }, loading: false, error: null })
    mockFetchDeckWithQuestions.mockResolvedValue({
      id: 'd1',
      title: 'My Deck',
      description: 'Desc',
      owner_id: 'u1',
      published: false,
      copied_from_deck_id: null,
      config: {},
      questions: [{ prompt: 'Q?', explanation: '', answers: ['A'], correct_answer_indices: [0] }],
    })
  })

  it('shows loading then form when deck owned by user', async () => {
    render(EditDeck, { props: { params: { id: 'd1' } } })
    expect(screen.getByText(/Loading deck/)).toBeInTheDocument()
    await waitFor(() => expect(screen.getByDisplayValue('My Deck')).toBeInTheDocument())
  })

  it('redirects when deck owner is not current user', async () => {
    mockFetchDeckWithQuestions.mockResolvedValue({
      id: 'd1',
      title: 'Other',
      owner_id: 'other-user',
      questions: [],
    })
    render(EditDeck, { props: { params: { id: 'd1' } } })
    await waitFor(() => expect(mockPush).toHaveBeenCalledWith('/'))
  })

  it('cancel calls push to home', async () => {
    render(EditDeck, { props: { params: { id: 'd1' } } })
    await waitFor(() => expect(screen.getByDisplayValue('My Deck')).toBeInTheDocument())
    await fireEvent.click(screen.getByRole('button', { name: 'Cancel' }))
    expect(mockPush).toHaveBeenCalledWith('/')
  })

  it('save calls updateDeck and pushes home', async () => {
    mockUpdateDeck.mockResolvedValue(undefined)
    render(EditDeck, { props: { params: { id: 'd1' } } })
    await waitFor(() => expect(screen.getByDisplayValue('My Deck')).toBeInTheDocument())
    await fireEvent.click(screen.getByRole('button', { name: 'Save' }))
    await waitFor(() => expect(mockUpdateDeck).toHaveBeenCalledWith(expect.anything(), 'd1', expect.any(Object)))
    expect(mockPush).toHaveBeenCalledWith('/')
  })
})
