import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';
import { AccountContext } from '../../contexts/AccountContext';
import { AuthContext } from '../../contexts/AuthContext';
import DeleteAccountSection from './DeleteAccountSection';

const mockDelete = jest.fn();
const mockPost = jest.fn();
const mockClearTokens = jest.fn();
const mockGetRefreshToken = jest.fn();
const mockApplyAccessToken = jest.fn();
const mockNavigate = jest.fn();
const mockSetAccount = jest.fn();
const mockSetAuthentication = jest.fn();
const mockTrackEvent = jest.fn();

jest.mock('../../../axiosApi', () => ({
  axiosInstance: {
    delete: (...args: unknown[]) => mockDelete(...args),
    post: (...args: unknown[]) => mockPost(...args),
  },
  applyAccessToken: (...args: unknown[]) => mockApplyAccessToken(...args),
}));

jest.mock('../../auth/tokenStorage', () => ({
  clearTokens: (...args: unknown[]) => mockClearTokens(...args),
  getRefreshToken: (...args: unknown[]) => mockGetRefreshToken(...args),
}));

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useNavigate: () => mockNavigate,
}));

jest.mock('../../utils/analytics', () => ({
  AnalyticsEvents: {
    ACCOUNT_DELETE_STARTED: 'Account Delete Started',
    ACCOUNT_DELETE_SUCCESS: 'Account Delete Success',
    ACCOUNT_DELETE_FAILED: 'Account Delete Failed',
  },
  trackEvent: (...args: unknown[]) => mockTrackEvent(...args),
}));

jest.mock('../../utils/revenueCat', () => ({
  logOutRevenueCat: () => Promise.resolve(),
}));

const theme = {
  main: '#4a90e2',
  darkMode: true,
  colors: {
    text: '#ffffff',
    cardBackground: 'rgba(0,0,0,0.4)',
    cardBorder: 'rgba(255,255,255,0.1)',
  },
};

const renderSection = () =>
  render(
    <MemoryRouter>
      <ThemeProvider theme={theme}>
        <AuthContext.Provider
          value={{
            authenticated: true,
            setAuthentication: mockSetAuthentication,
            needsNewPassword: false,
            setNeedsNewPassword: () => {},
            loading: false,
          }}
        >
          <AccountContext.Provider
            value={{
              account: { email: 'user@example.com' } as never,
              setAccount: mockSetAccount,
            }}
          >
            <DeleteAccountSection />
          </AccountContext.Provider>
        </AuthContext.Provider>
      </ThemeProvider>
    </MemoryRouter>
  );

describe('DeleteAccountSection', () => {
  beforeEach(() => {
    mockDelete.mockReset();
    mockPost.mockReset();
    mockClearTokens.mockReset();
    mockGetRefreshToken.mockReset();
    mockApplyAccessToken.mockReset();
    mockNavigate.mockReset();
    mockSetAccount.mockReset();
    mockSetAuthentication.mockReset();
    mockTrackEvent.mockReset();
    mockGetRefreshToken.mockReturnValue('refresh-token');
    mockClearTokens.mockResolvedValue(undefined);
    mockDelete.mockResolvedValue({ data: { deleted: true } });
    mockPost.mockResolvedValue({});
  });

  it('requires email confirmation then deletes and signs out', async () => {
    const user = userEvent.setup();
    renderSection();

    await user.click(screen.getByRole('button', { name: /Delete my account/i }));
    expect(await screen.findByTestId('delete-account-modal')).toBeInTheDocument();

    await user.type(screen.getByLabelText(/Confirm email/i), 'user@example.com');
    await user.click(screen.getByRole('button', { name: /^Delete account$/i }));

    await waitFor(() => {
      expect(mockDelete).toHaveBeenCalledWith('/user/', {
        data: { refresh_token: 'refresh-token' },
      });
    });
    expect(mockTrackEvent).toHaveBeenCalledWith('Account Delete Started');
    expect(mockTrackEvent).toHaveBeenCalledWith('Account Delete Success');
    expect(mockClearTokens).toHaveBeenCalled();
    expect(mockApplyAccessToken).toHaveBeenCalledWith(null);
    expect(mockSetAuthentication).toHaveBeenCalledWith(false);
    expect(mockNavigate).toHaveBeenCalledWith('/signin/');
  });
});
