// REQ-USR-004: RequireAuth 守卫三态（BR1） — authResolving / unauthenticated / ready
import { describe, it, expect } from 'vitest';
import { screen } from '@testing-library/react';
import { Routes, Route, useLocation } from 'react-router-dom';
import { renderShell, type RenderShellOptions } from './renderShell';
import RequireAuth from '../../src/router/RequireAuth';

// 哨兵：登录页读出 state.from，便于断言重定向携带来源
function LoginSentinel() {
  const loc = useLocation();
  const from = (loc.state as { from?: string } | null)?.from;
  return <div data-testid="login-sentinel">login from={from ?? 'none'}</div>;
}

function ProtectedSentinel() {
  return <div data-testid="protected-sentinel">protected-content</div>;
}

function renderGuard(initialEntries: string[], preloadedAuth?: RenderShellOptions['preloadedAuth']) {
  return renderShell(
    <Routes>
      <Route path="/login" element={<LoginSentinel />} />
      <Route element={<RequireAuth />}>
        <Route path="/" element={<ProtectedSentinel />} />
      </Route>
    </Routes>,
    { initialEntries, preloadedAuth },
  );
}

describe('RequireAuth', () => {
  it('redirects to /login when no token', () => {
    renderGuard(['/'], { token: null, user: null });
    expect(screen.getByTestId('login-sentinel')).toBeInTheDocument();
    expect(screen.getByText(/from=\//)).toBeInTheDocument();
    expect(screen.queryByTestId('protected-sentinel')).not.toBeInTheDocument();
  });

  it('renders Spin placeholder when token present but user not resolved', () => {
    renderGuard(['/'], { token: 't', user: null });
    expect(screen.getByTestId('auth-resolving')).toBeInTheDocument();
    expect(screen.queryByTestId('protected-sentinel')).not.toBeInTheDocument();
    expect(screen.queryByTestId('login-sentinel')).not.toBeInTheDocument();
  });

  it('renders protected content when token and user ready', () => {
    renderGuard(['/'], {
      token: 't',
      user: { id: 1, sUserName: '朱子纯', sUserType: '超级管理员', sLanguage: '中文' },
    });
    expect(screen.getByTestId('protected-sentinel')).toBeInTheDocument();
  });
});
