import { render, screen } from '@testing-library/react'
import { delay, http, HttpResponse } from 'msw'
import { MemoryRouter, Route, Routes } from 'react-router'
import { describe, expect, it } from 'vitest'
import { server } from '../test/server'
import { AuthProvider } from './AuthProvider'
import { RequireAuth, RequireGuest } from './guards'

/**
 * Minimal route tree exercising both guards, mirroring the real router
 * skeleton: a guest-only /login and an auth-only app placeholder at /.
 */
function GuardedApp() {
  return (
    <AuthProvider>
      <Routes>
        <Route element={<RequireGuest />}>
          <Route path="/login" element={<div>LOGIN</div>} />
        </Route>
        <Route element={<RequireAuth />}>
          <Route path="/" element={<div>SCENARIOS</div>} />
        </Route>
      </Routes>
    </AuthProvider>
  )
}

describe('RequireAuth', () => {
  it('redirects an unauthenticated user to /login', async () => {
    server.use(
      http.get('http://localhost/api/me', () =>
        HttpResponse.json({ message: 'unauthorized' }, { status: 401 }),
      ),
    )

    render(
      <MemoryRouter initialEntries={['/']}>
        <GuardedApp />
      </MemoryRouter>,
    )

    expect(await screen.findByText('LOGIN')).toBeInTheDocument()
    expect(screen.queryByText('SCENARIOS')).not.toBeInTheDocument()
  })

  it('renders children for an authenticated user', async () => {
    server.use(
      http.get('http://localhost/api/me', () =>
        HttpResponse.json({ id: 'u1', email: 'a@b.com' }),
      ),
    )

    render(
      <MemoryRouter initialEntries={['/']}>
        <GuardedApp />
      </MemoryRouter>,
    )

    expect(await screen.findByText('SCENARIOS')).toBeInTheDocument()
    expect(screen.queryByText('LOGIN')).not.toBeInTheDocument()
  })
})

describe('RequireGuest', () => {
  it('redirects an authenticated user away from /login', async () => {
    server.use(
      http.get('http://localhost/api/me', () =>
        HttpResponse.json({ id: 'u1', email: 'a@b.com' }),
      ),
    )

    render(
      <MemoryRouter initialEntries={['/login']}>
        <GuardedApp />
      </MemoryRouter>,
    )

    expect(await screen.findByText('SCENARIOS')).toBeInTheDocument()
    expect(screen.queryByText('LOGIN')).not.toBeInTheDocument()
  })
})

describe('auth probe loading state (no flash)', () => {
  it('does not flash protected or login content while the auth probe is pending', async () => {
    server.use(
      http.get('http://localhost/api/me', async () => {
        await delay(50)
        return HttpResponse.json({ id: 'u1', email: 'a@b.com' })
      }),
    )

    render(
      <MemoryRouter initialEntries={['/']}>
        <GuardedApp />
      </MemoryRouter>,
    )

    expect(screen.queryByText('SCENARIOS')).not.toBeInTheDocument()
    expect(screen.queryByText('LOGIN')).not.toBeInTheDocument()

    expect(await screen.findByText('SCENARIOS')).toBeInTheDocument()
  })
})
