import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { MemoryRouter } from 'react-router-dom'
import { Layout } from './Layout'

vi.mock('../hooks/useTheme', () => ({
  useTheme: () => ({ theme: 'dark' as const, toggle: vi.fn() }),
}))

const mockUseAuth = vi.fn()
vi.mock('../contexts/AuthContext', () => ({
  useAuth: () => mockUseAuth(),
}))

const loggedOutAuth = {
  user: null,
  session: null,
  loading: false,
  isAdmin: false,
  signInWithEmail: vi.fn(),
  signUpWithEmail: vi.fn(),
  signInWithGoogle: vi.fn(),
  signInWithDiscord: vi.fn(),
  signOut: vi.fn(),
}

const adminAuth = {
  ...loggedOutAuth,
  user: { email: 'admin@example.com' },
  session: {},
  isAdmin: true,
}

function renderLayout(initialPath = '/') {
  return render(
    <MemoryRouter initialEntries={[initialPath]}>
      <Layout />
    </MemoryRouter>
  )
}

describe('Layout', () => {
  describe('when logged out', () => {
    beforeEach(() => mockUseAuth.mockReturnValue(loggedOutAuth))

    it('renders logged-out navigation links', () => {
      renderLayout()
      expect(screen.getAllByRole('link', { name: /^home$/i })[0]).toBeInTheDocument()
      expect(screen.getAllByRole('link', { name: /^runs$/i })[0]).toBeInTheDocument()
      expect(screen.getAllByRole('link', { name: /genlockes/i })[0]).toBeInTheDocument()
      expect(screen.getAllByRole('link', { name: /stats/i })[0]).toBeInTheDocument()
    })

    it('does not show authenticated links', () => {
      renderLayout()
      expect(screen.queryByRole('link', { name: /new run/i })).not.toBeInTheDocument()
      expect(screen.queryByRole('link', { name: /my runs/i })).not.toBeInTheDocument()
      expect(screen.queryByRole('link', { name: /admin/i })).not.toBeInTheDocument()
    })

    it('shows sign-in link', () => {
      renderLayout()
      expect(screen.getByRole('link', { name: /sign in/i })).toBeInTheDocument()
    })
  })

  describe('when logged in as admin', () => {
    beforeEach(() => mockUseAuth.mockReturnValue(adminAuth))

    it('renders authenticated navigation links', () => {
      renderLayout()
      expect(screen.getAllByRole('link', { name: /new run/i })[0]).toBeInTheDocument()
      expect(screen.getAllByRole('link', { name: /my runs/i })[0]).toBeInTheDocument()
      expect(screen.getAllByRole('link', { name: /genlockes/i })[0]).toBeInTheDocument()
      expect(screen.getAllByRole('link', { name: /stats/i })[0]).toBeInTheDocument()
      expect(screen.getAllByRole('link', { name: /admin/i })[0]).toBeInTheDocument()
    })

    it('shows the mobile dropdown when the hamburger is clicked', async () => {
      renderLayout()
      const hamburger = screen.getByRole('button', { name: /toggle menu/i })
      await userEvent.click(hamburger)
      expect(screen.getAllByRole('link', { name: /my runs/i }).length).toBeGreaterThan(1)
    })
  })

  it('renders the brand logo link', () => {
    mockUseAuth.mockReturnValue(loggedOutAuth)
    renderLayout()
    expect(screen.getByRole('link', { name: /ant/i })).toBeInTheDocument()
  })

  it('renders the theme toggle button', () => {
    mockUseAuth.mockReturnValue(loggedOutAuth)
    renderLayout()
    expect(screen.getAllByRole('button', { name: /switch to light mode/i })[0]).toBeInTheDocument()
  })

  it('initially hides the mobile dropdown menu', () => {
    mockUseAuth.mockReturnValue(loggedOutAuth)
    renderLayout()
    expect(screen.getByRole('button', { name: /toggle menu/i })).toBeInTheDocument()
  })

  it('renders the footer with PokeDB attribution', () => {
    mockUseAuth.mockReturnValue(loggedOutAuth)
    renderLayout()
    expect(screen.getByRole('link', { name: /pokedb/i })).toBeInTheDocument()
  })
})
