import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { UserProfile } from './UserProfile';
import { apiClient } from '@/services/api/client';

// Mock apiClient
vi.mock('@/services/api/client', () => ({
  apiClient: {
    get: vi.fn(),
  },
}));

// Mock ResizeObserver for tests
global.ResizeObserver = vi.fn().mockImplementation(() => ({
  observe: vi.fn(),
  unobserve: vi.fn(),
  disconnect: vi.fn(),
}));

const TestWrapper = ({ children }: { children: React.ReactNode }) => {
  return <BrowserRouter>{children}</BrowserRouter>;
};

describe('UserProfile Component', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  // Test 1: Affiche le nombre de sessions actives
  it('should display active sessions count', async () => {
    vi.mocked(apiClient.get).mockResolvedValue({
      data: {
        sessions: [
          {
            id: '1',
            ip_address: '192.168.1.1',
            user_agent: 'Mozilla/5.0',
            last_activity: '2024-01-15T10:30:00Z',
            created_at: '2024-01-10T08:00:00Z',
            is_current: true,
          },
          {
            id: '2',
            ip_address: '192.168.1.2',
            user_agent: 'Mozilla/5.0',
            last_activity: '2024-01-15T09:00:00Z',
            created_at: '2024-01-12T12:00:00Z',
            is_current: false,
          },
        ],
        count: 2,
      },
    });

    render(
      <TestWrapper>
        <UserProfile />
      </TestWrapper>,
    );

    await waitFor(() => {
      expect(screen.getByText('Active Sessions')).toBeInTheDocument();
      expect(screen.getByText('2')).toBeInTheDocument();
    });

    expect(apiClient.get).toHaveBeenCalledWith('/auth/sessions');
  });

  // Test 2: Affiche 0 quand il n'y a pas de sessions
  it('should display 0 when there are no sessions', async () => {
    vi.mocked(apiClient.get).mockResolvedValue({
      data: {
        sessions: [],
        count: 0,
      },
    });

    render(
      <TestWrapper>
        <UserProfile />
      </TestWrapper>,
    );

    await waitFor(() => {
      expect(screen.getByText('0')).toBeInTheDocument();
    });
  });

  // Test 3: Affiche le lien vers /settings/sessions
  it('should display link to /settings/sessions', async () => {
    vi.mocked(apiClient.get).mockResolvedValue({
      data: {
        sessions: [],
        count: 0,
      },
    });

    render(
      <TestWrapper>
        <UserProfile />
      </TestWrapper>,
    );

    await waitFor(() => {
      const link = screen.getByText('Manage Sessions').closest('a');
      expect(link).toBeInTheDocument();
      expect(link).toHaveAttribute('href', '/settings/sessions');
    });
  });

  // Test 4: Gère les erreurs de récupération
  it('should handle fetch errors gracefully', async () => {
    vi.mocked(apiClient.get).mockRejectedValue({
      response: {
        data: {
          error: 'Failed to fetch sessions',
        },
      },
    });

    render(
      <TestWrapper>
        <UserProfile />
      </TestWrapper>,
    );

    await waitFor(() => {
      // Le composant devrait toujours s'afficher même en cas d'erreur
      expect(screen.getByText('Active Sessions')).toBeInTheDocument();
      // Il devrait afficher 0 ou "Error" en cas d'erreur
      expect(screen.getByText('Error')).toBeInTheDocument();
    });
  });

  // Test bonus: Affiche "Loading..." pendant le chargement
  it('should display loading state while fetching', () => {
    vi.mocked(apiClient.get).mockImplementation(
      () => new Promise(() => {}), // Never resolves
    );

    render(
      <TestWrapper>
        <UserProfile />
      </TestWrapper>,
    );

    expect(screen.getByText('Loading...')).toBeInTheDocument();
  });
});
