import { describe, it, expect, vi, afterEach } from 'vitest';
import { render, waitFor, screen } from '@solidjs/testing-library';
import { Router, Route } from '@solidjs/router';
import { AuthProvider, useAuth } from '~/contexts/AuthContext';
import { I18nProvider } from '~/i18n';
import { ToastProvider } from '~/components/ui/Toast';
import { authApi } from '~/api/auth';
import type { User } from '~/types';

vi.mock('~/api/auth', () => ({
  authApi: {
    me: vi.fn(),
    logout: vi.fn(),
  },
}));

const mockedMe = vi.mocked(authApi.me);

afterEach(() => {
  vi.clearAllMocks();
});

const adminUser: User = {
  id: '1',
  email: 'admin@example.com',
  display_name: 'Admin',
  role: 'admin',
  created_at: '2026-01-01T00:00:00Z',
};

const regularUser: User = {
  id: '2',
  email: 'user@example.com',
  display_name: 'User',
  role: 'user',
  created_at: '2026-01-01T00:00:00Z',
};

describe('Admin Route Guard', () => {
  it('should expose isAdmin as true for admin users', async () => {
    mockedMe.mockResolvedValue(adminUser);

    const TestComponent = () => {
      const { isAdmin, loading } = useAuth();
      return (
        <div>
          <span data-testid="loading">{loading() ? 'true' : 'false'}</span>
          <span data-testid="isAdmin">{isAdmin() ? 'true' : 'false'}</span>
        </div>
      );
    };

    render(() => (
      <I18nProvider locale="fr">
        <ToastProvider>
          <AuthProvider>
            <TestComponent />
          </AuthProvider>
        </ToastProvider>
      </I18nProvider>
    ));

    await waitFor(() => {
      expect(screen.getByTestId('loading').textContent).toBe('false');
    });

    expect(screen.getByTestId('isAdmin').textContent).toBe('true');
  });

  it('should expose isAdmin as false for non-admin users', async () => {
    mockedMe.mockResolvedValue(regularUser);

    const TestComponent = () => {
      const { isAdmin, loading } = useAuth();
      return (
        <div>
          <span data-testid="loading">{loading() ? 'true' : 'false'}</span>
          <span data-testid="isAdmin">{isAdmin() ? 'true' : 'false'}</span>
        </div>
      );
    };

    render(() => (
      <I18nProvider locale="fr">
        <ToastProvider>
          <AuthProvider>
            <TestComponent />
          </AuthProvider>
        </ToastProvider>
      </I18nProvider>
    ));

    await waitFor(() => {
      expect(screen.getByTestId('loading').textContent).toBe('false');
    });

    expect(screen.getByTestId('isAdmin').textContent).toBe('false');
  });

  it('should expose isAdmin as false when user is null', async () => {
    mockedMe.mockRejectedValue(new Error('Unauthorized'));

    const TestComponent = () => {
      const { isAdmin, loading } = useAuth();
      return (
        <div>
          <span data-testid="loading">{loading() ? 'true' : 'false'}</span>
          <span data-testid="isAdmin">{isAdmin() ? 'true' : 'false'}</span>
        </div>
      );
    };

    render(() => (
      <I18nProvider locale="fr">
        <ToastProvider>
          <AuthProvider>
            <TestComponent />
          </AuthProvider>
        </ToastProvider>
      </I18nProvider>
    ));

    await waitFor(() => {
      expect(screen.getByTestId('loading').textContent).toBe('false');
    });

    expect(screen.getByTestId('isAdmin').textContent).toBe('false');
  });
});
