import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { I18nextProvider } from 'react-i18next';
import { ThemeProvider } from 'styled-components';
import ProfileSessionsPage from '@/features/profile/pages/ProfileSessionsPage';
import { authService } from '@/features/auth/services/authService';
import i18n from '@/locales/i18n';
import { LocaleProvider } from '@/app/providers/LocaleProvider';
import { lightTheme } from '@/styles/theme';

vi.mock('@/features/auth/services/authService', () => ({
  authService: {
    listSessions: vi.fn(),
    revokeSession: vi.fn(),
    revokeOtherSessions: vi.fn(),
    logout: vi.fn(),
  },
}));

vi.mock('@/shared/components/layout/AppLayout', () => ({
  AppLayout: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
}));

const sampleSessions = [
  {
    id: 'session-1',
    device_name: 'Chrome on macOS',
    ip_address: '127.0.0.1',
    last_used_at: '2026-05-18T10:00:00Z',
    trusted_until: null,
    is_trusted: false,
    is_current: true,
    created_at: '2026-05-18T09:00:00Z',
  },
  {
    id: 'session-2',
    device_name: 'Safari on iPhone',
    ip_address: '10.0.0.2',
    last_used_at: '2026-05-17T10:00:00Z',
    trusted_until: '2026-06-18T10:00:00Z',
    is_trusted: true,
    is_current: false,
    created_at: '2026-05-17T09:00:00Z',
  },
];

function renderPage() {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });

  return render(
    <QueryClientProvider client={queryClient}>
      <I18nextProvider i18n={i18n}>
        <LocaleProvider>
          <ThemeProvider theme={lightTheme}>
            <MemoryRouter>
              <ProfileSessionsPage />
            </MemoryRouter>
          </ThemeProvider>
        </LocaleProvider>
      </I18nextProvider>
    </QueryClientProvider>,
  );
}

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

  it('shows loading then session list', async () => {
    vi.mocked(authService.listSessions).mockResolvedValue(sampleSessions);

    renderPage();

    expect(await screen.findByText(/chrome on macos/i)).toBeInTheDocument();
    expect(screen.getByText(/safari on iphone/i)).toBeInTheDocument();
  });

  it('shows error state when sessions fail to load', async () => {
    vi.mocked(authService.listSessions).mockRejectedValue(new Error('network'));

    renderPage();

    expect(await screen.findByRole('alert')).toHaveTextContent(/could not load sessions/i);
  });

  it('revokes another session after confirmation', async () => {
    const user = userEvent.setup();
    vi.mocked(authService.listSessions)
      .mockResolvedValueOnce(sampleSessions)
      .mockResolvedValueOnce([sampleSessions[0]!]);
    vi.mocked(authService.revokeSession).mockResolvedValue(undefined);

    renderPage();

    await screen.findByText(/safari on iphone/i);
    const revokeButtons = screen.getAllByRole('button', { name: /^revoke$/i });
    await user.click(revokeButtons[0]!);
    await user.click(screen.getByRole('button', { name: /^confirm$/i }));

    await waitFor(() => {
      expect(authService.revokeSession).toHaveBeenCalledWith('session-2');
    });
  });

  it('revokes other sessions', async () => {
    const user = userEvent.setup();
    vi.mocked(authService.listSessions).mockResolvedValue(sampleSessions);
    vi.mocked(authService.revokeOtherSessions).mockResolvedValue(undefined);

    renderPage();

    await screen.findByText(/chrome on macos/i);
    await user.click(screen.getByRole('button', { name: /revoke all other sessions/i }));
    await user.click(screen.getByRole('button', { name: /^confirm$/i }));

    await waitFor(() => {
      expect(authService.revokeOtherSessions).toHaveBeenCalled();
    });
  });
});
