import { describe, it, expect, vi } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { AuthProviderWithDevBridge } from './AuthProviderWithDevBridge';
import { useAuth } from './useAuth';
import type { DevUserMapper } from './AuthProviderWithDevBridge';
import type { DevUserState } from '@lilith/ui-dev-tools';
import { UserRole, UserType } from '@lilith/types';

// Mock @lilith/ui-dev-tools
vi.mock('@lilith/ui-dev-tools', () => ({
  useDevUser: vi.fn(),
}));

// Mock @lilith/sso-client
vi.mock('@lilith/sso-client', () => ({
  SSOClient: vi.fn().mockImplementation(() => ({
    checkSession: vi.fn().mockResolvedValue({ authenticated: false, user: null }),
    startAutoCheck: vi.fn(),
    destroy: vi.fn(),
  })),
}));

// Mock auth-events
vi.mock('./auth-events', () => ({
  authEvents: {
    initialize: vi.fn(),
    subscribe: vi.fn(() => vi.fn()),
    destroy: vi.fn(),
    broadcast: vi.fn(),
  },
}));

import { useDevUser } from '@lilith/ui-dev-tools';

const mockUseDevUser = vi.mocked(useDevUser);

// Test component that uses useAuth hook
function TestComponent() {
  const { isAuthenticated, user, isDevMode } = useAuth();

  return (
    <div>
      <div data-testid="is-authenticated">{String(isAuthenticated)}</div>
      <div data-testid="is-dev-mode">{String(isDevMode)}</div>
      {user && (
        <>
          <div data-testid="user-id">{user.id}</div>
          <div data-testid="user-email">{user.email}</div>
          <div data-testid="user-role">{user.role}</div>
          <div data-testid="user-types">{user.userTypes.join(',')}</div>
        </>
      )}
    </div>
  );
}

describe('Dev Auth Integration', () => {
  const mapDevUser: DevUserMapper = (devUser: DevUserState) => ({
    id: devUser.userId || 'dev-id',
    email: `${devUser.primaryType}@test.local`,
    username: devUser.displayName || 'Dev User',
    role: devUser.primaryType === 'admin' ? UserRole.ADMIN : UserRole.USER,
    userTypes: devUser.primaryType === 'provider'
      ? [UserType.ESCORT]
      : devUser.primaryType === 'client'
        ? [UserType.CLIENT]
        : [],
    primaryUserType: devUser.primaryType === 'provider'
      ? UserType.ESCORT
      : devUser.primaryType === 'client'
        ? UserType.CLIENT
        : undefined,
    isActive: true,
    emailVerified: true,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
  });

  it('should propagate dev auth state to useAuth hook', async () => {
    const queryClient = new QueryClient({
      defaultOptions: { queries: { retry: false } },
    });

    mockUseDevUser.mockReturnValue({
      userTypes: ['provider'],
      primaryType: 'provider',
      isAuthenticated: true,
      hasDeclaredIntent: true,
      displayName: 'Test Provider',
      userId: 'provider-123',
      isDevMode: true,
      addType: vi.fn(),
      removeType: vi.fn(),
      setPrimaryType: vi.fn(),
      toggleType: vi.fn(),
      hasType: vi.fn(),
      canBePrimary: vi.fn(),
      signOut: vi.fn(),
      signInAsDefault: vi.fn(),
      userTypeConfigs: [],
      getTypeConfig: vi.fn(),
    });

    render(
      <QueryClientProvider client={queryClient}>
        <AuthProviderWithDevBridge ssoUrl="https://sso.test" mapDevUser={mapDevUser}>
          <TestComponent />
        </AuthProviderWithDevBridge>
      </QueryClientProvider>
    );

    await waitFor(() => {
      expect(screen.getByTestId('is-authenticated').textContent).toBe('true');
      expect(screen.getByTestId('is-dev-mode').textContent).toBe('true');
      expect(screen.getByTestId('user-id').textContent).toBe('provider-123');
      expect(screen.getByTestId('user-email').textContent).toBe('provider@test.local');
      expect(screen.getByTestId('user-role').textContent).toBe(UserRole.USER);
      expect(screen.getByTestId('user-types').textContent).toBe('escort');
    });
  });

  it('should show guest state when dev user is not authenticated', async () => {
    const queryClient = new QueryClient({
      defaultOptions: { queries: { retry: false } },
    });

    mockUseDevUser.mockReturnValue({
      userTypes: [],
      primaryType: null,
      isAuthenticated: false,
      hasDeclaredIntent: false,
      displayName: 'Guest',
      userId: null,
      isDevMode: true,
      addType: vi.fn(),
      removeType: vi.fn(),
      setPrimaryType: vi.fn(),
      toggleType: vi.fn(),
      hasType: vi.fn(),
      canBePrimary: vi.fn(),
      signOut: vi.fn(),
      signInAsDefault: vi.fn(),
      userTypeConfigs: [],
      getTypeConfig: vi.fn(),
    });

    render(
      <QueryClientProvider client={queryClient}>
        <AuthProviderWithDevBridge ssoUrl="https://sso.test" mapDevUser={mapDevUser}>
          <TestComponent />
        </AuthProviderWithDevBridge>
      </QueryClientProvider>
    );

    await waitFor(() => {
      expect(screen.getByTestId('is-authenticated').textContent).toBe('false');
      expect(screen.queryByTestId('user-id')).not.toBeInTheDocument();
    });
  });

  it('should correctly map admin role', async () => {
    const queryClient = new QueryClient({
      defaultOptions: { queries: { retry: false } },
    });

    mockUseDevUser.mockReturnValue({
      userTypes: ['admin'],
      primaryType: 'admin',
      isAuthenticated: true,
      hasDeclaredIntent: true,
      displayName: 'Admin User',
      userId: 'admin-999',
      isDevMode: true,
      addType: vi.fn(),
      removeType: vi.fn(),
      setPrimaryType: vi.fn(),
      toggleType: vi.fn(),
      hasType: vi.fn(),
      canBePrimary: vi.fn(),
      signOut: vi.fn(),
      signInAsDefault: vi.fn(),
      userTypeConfigs: [],
      getTypeConfig: vi.fn(),
    });

    render(
      <QueryClientProvider client={queryClient}>
        <AuthProviderWithDevBridge ssoUrl="https://sso.test" mapDevUser={mapDevUser}>
          <TestComponent />
        </AuthProviderWithDevBridge>
      </QueryClientProvider>
    );

    await waitFor(() => {
      expect(screen.getByTestId('user-role').textContent).toBe(UserRole.ADMIN);
    });
  });
});
