import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte'
import Settings from './Settings.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 mockGetProfile = vi.fn()
const mockUpdateProfile = vi.fn()
const mockUploadAvatar = vi.fn()
vi.mock('../lib/api/profile.js', () => ({
  getProfile: (...args) => mockGetProfile(...args),
  updateProfile: (...args) => mockUpdateProfile(...args),
  uploadAvatar: (...args) => mockUploadAvatar(...args),
}))

describe('Settings', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    auth.set({ user: { id: 'u1' }, loading: false, error: null })
    mockGetProfile.mockResolvedValue({
      id: 'u1',
      display_name: 'Test User',
      email: 'test@example.com',
      avatar_url: null,
    })
    mockUpdateProfile.mockResolvedValue({})
  })

  it('loads profile and shows display name', async () => {
    render(Settings)
    await waitFor(() => expect(screen.getByDisplayValue('Test User')).toBeInTheDocument())
    expect(mockGetProfile).toHaveBeenCalledWith('u1')
  })

  it('Cancel button calls push to home', async () => {
    render(Settings)
    await waitFor(() => expect(screen.getByDisplayValue('Test User')).toBeInTheDocument())
    await fireEvent.click(screen.getByRole('button', { name: 'Cancel' }))
    expect(mockPush).toHaveBeenCalledWith('/')
  })

  it('shows error for non-image file', async () => {
    render(Settings)
    await waitFor(() => expect(screen.getByDisplayValue('Test User')).toBeInTheDocument())
    const input = document.querySelector('input[type="file"]')
    expect(input).toBeTruthy()
    const file = new File(['x'], 'doc.pdf', { type: 'application/pdf' })
    await fireEvent.change(input, { target: { files: [file] } })
    expect(screen.getByText(/Please choose an image file/)).toBeInTheDocument()
  })

  it('save updates profile and shows success', async () => {
    mockGetProfile
      .mockResolvedValueOnce({ id: 'u1', display_name: 'Test User', email: 't@t.com', avatar_url: null })
      .mockResolvedValueOnce({ id: 'u1', display_name: 'New Name', email: 't@t.com', avatar_url: null })
    render(Settings)
    await waitFor(() => expect(screen.getByDisplayValue('Test User')).toBeInTheDocument())
    const nameInput = screen.getByDisplayValue('Test User')
    await fireEvent.input(nameInput, { target: { value: 'New Name' } })
    await fireEvent.click(screen.getByRole('button', { name: 'Save' }))
    await waitFor(() =>
      expect(mockUpdateProfile).toHaveBeenCalledWith('u1', { display_name: 'New Name', avatar_url: null })
    )
    await waitFor(() => expect(screen.getByText('Settings saved.')).toBeInTheDocument())
  })
})
