import React from 'react';
import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';

import VerifyEmailPage from './views/VerifyEmailPage';
import { I18nProvider } from './i18n/I18nProvider';
import { api, getApiErrorMessage } from './api';

const mockedApi = api as jest.Mocked<typeof api>;
// CRA's jest config sets resetMocks: true, which wipes the initial implementation given to
// jest.fn() in setupTests.ts before every test -- re-arm it here so error-derived text is testable.
const mockedGetApiErrorMessage = getApiErrorMessage as jest.Mock;

function renderVerifyEmailPage(search: string, emailChange = false) {
  const path = emailChange ? '/confirm-email-change' : '/verify-email';
  window.history.pushState({}, '', `${path}${search}`);
  return render(
    <MemoryRouter initialEntries={[`${path}${search}`]}>
      <I18nProvider>
        <VerifyEmailPage emailChange={emailChange} />
      </I18nProvider>
    </MemoryRouter>,
  );
}

describe('VerifyEmailPage', () => {
  beforeEach(() => {
    mockedApi.post.mockReset();
    mockedGetApiErrorMessage.mockImplementation((e: any, fallback?: string) => {
      const data = e?.response?.data;
      return typeof data === 'string' && data.trim() ? data.trim() : fallback;
    });
  });

  it('confirms the account and shows success when the link is valid', async () => {
    mockedApi.post.mockResolvedValueOnce({ data: {} } as any);

    renderVerifyEmailPage('?userId=user-1&token=good-token');

    expect(await screen.findByText('Your email has been verified. You can now sign in.')).toBeInTheDocument();
    expect(mockedApi.post).toHaveBeenCalledWith('/auth/verify-email', { userId: 'user-1', token: 'good-token' });
  });

  it('shows an error when the link is invalid or expired', async () => {
    mockedApi.post.mockRejectedValueOnce({ response: { status: 400, data: 'Invalid or expired link.' } });

    renderVerifyEmailPage('?userId=user-1&token=bad-token');

    expect(await screen.findByText('Invalid or expired link.')).toBeInTheDocument();
  });

  it('shows an error without calling the API when the link is missing userId/token', async () => {
    renderVerifyEmailPage('');

    expect(await screen.findByText('Missing user/token in link.')).toBeInTheDocument();
    expect(mockedApi.post).not.toHaveBeenCalled();
  });

  it('confirms a pending email change and requires a fresh sign-in', async () => {
    mockedApi.post.mockResolvedValueOnce({ data: {} } as any);

    renderVerifyEmailPage('?userId=user-1&email=new%40example.com&token=change-token', true);

    expect(await screen.findByText('Your email has changed. Sign in again with the new address.')).toBeInTheDocument();
    expect(mockedApi.post).toHaveBeenCalledWith('/auth/email-change/confirm', { userId: 'user-1', email: 'new@example.com', token: 'change-token' });
  });
});
