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

import CvBuilderPage from './views/CvBuilderPage';
import { I18nProvider } from './i18n/I18nProvider';
import { ToastProvider } from './toast';
import { api } from './api';
import { ConfirmProvider } from './confirm';
import { PromptProvider } from './prompt';

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

jest.mock('./api', () => ({
  api: {
    get: jest.fn(),
    post: jest.fn(),
    put: jest.fn(),
    patch: jest.fn(),
    delete: jest.fn(),
    interceptors: { request: { use: jest.fn() }, response: { use: jest.fn() } },
  },
  getApiErrorMessage: (_error: any, fallback?: string) => fallback || 'Request failed.',
}));

const mockedApi = api as jest.Mocked<typeof api>;

function renderPage() {
  return render(
    <MemoryRouter>
      <ToastProvider>
        <I18nProvider>
          <ConfirmProvider>
            <PromptProvider>
              <CvBuilderPage />
            </PromptProvider>
          </ConfirmProvider>
        </I18nProvider>
      </ToastProvider>
    </MemoryRouter>,
  );
}

beforeEach(() => {
  window.localStorage.removeItem('uiLanguage');
  jest.clearAllMocks();
});

afterEach(() => window.localStorage.removeItem('uiLanguage'));

test('lists existing CVs from the variants API', async () => {
  mockedApi.get.mockResolvedValueOnce({
    data: [
      { id: 1, name: 'Frontend CV', themeId: 'modern', language: 'en', publicSlug: 'abc', isPublic: true, version: 2, jobApplicationId: 17, jobTitle: 'Frontend Engineer', companyName: 'Northstar', updatedAtUtc: new Date().toISOString() },
    ],
  } as any);

  renderPage();

  expect(await screen.findByText('Frontend CV')).toBeInTheDocument();
  expect(screen.getByText('Public')).toBeInTheDocument();
  expect(screen.getByText(/Frontend Engineer at Northstar/)).toBeInTheDocument();
  const cvCard = screen.getByRole('link', { name: 'Open Frontend CV' });
  cvCard.focus();
  expect(cvCard).toHaveFocus();
  fireEvent.keyDown(cvCard, { key: 'Enter' });
  expect(mockNavigate).toHaveBeenCalledWith('/career/builder/1');
  expect(mockedApi.get).toHaveBeenCalledWith('/cv/variants');
});

test('shows the empty state and creates a CV then navigates to the editor', async () => {
  mockedApi.get.mockResolvedValueOnce({ data: [] } as any);
  mockedApi.post.mockResolvedValueOnce({ data: { id: 42 } } as any);

  renderPage();

  expect(await screen.findByText('No CVs yet')).toBeInTheDocument();

  fireEvent.click(screen.getAllByRole('button', { name: /New CV/i })[0]);

  expect(await screen.findByRole('dialog', { name: 'Create a CV' })).toBeInTheDocument();
  fireEvent.click(screen.getByRole('button', { name: 'Create CV' }));

  await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith('/cv/variants', expect.objectContaining({ name: 'Untitled CV' })));
  await waitFor(() => expect(mockNavigate).toHaveBeenCalledWith('/career/builder/42'));
});

test('CV dashboard and create flow render in Bokmål', async () => {
  window.localStorage.setItem('uiLanguage', 'nb');
  mockedApi.get.mockResolvedValueOnce({ data: [] } as any);

  renderPage();

  expect(await screen.findByText('Ingen CV-er ennå')).toBeInTheDocument();
  fireEvent.click(screen.getAllByRole('button', { name: 'Ny CV' })[0]);
  expect(await screen.findByRole('dialog', { name: 'Opprett en CV' })).toBeInTheDocument();
  expect(screen.getByLabelText('CV-navn')).toHaveValue('CV uten tittel');
  expect(screen.getByText('Velg en mal')).toBeInTheDocument();
});

test('CV deletion requires confirmation and supports cancellation', async () => {
  mockedApi.get.mockResolvedValueOnce({ data: [
    { id: 1, name: 'Frontend CV', themeId: 'modern', publicSlug: 'abc', isPublic: false, version: 2, jobApplicationId: null, updatedAtUtc: new Date().toISOString() },
  ] } as any);
  mockedApi.delete.mockResolvedValue({ data: null } as any);
  renderPage();

  await screen.findByText('Frontend CV');
  fireEvent.click(screen.getByRole('button', { name: 'Actions for Frontend CV' }));
  fireEvent.click(await screen.findByRole('menuitem', { name: 'Delete' }));
  expect(await screen.findByRole('dialog', { name: 'Delete CV' })).toBeInTheDocument();
  fireEvent.click(screen.getByRole('button', { name: 'Cancel' }));
  await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());
  expect(mockedApi.delete).not.toHaveBeenCalled();

  fireEvent.click(screen.getByRole('button', { name: 'Actions for Frontend CV' }));
  fireEvent.click(await screen.findByRole('menuitem', { name: 'Delete' }));
  fireEvent.click(await screen.findByRole('button', { name: 'Delete CV' }));
  await waitFor(() => expect(mockedApi.delete).toHaveBeenCalledWith('/cv/variants/1'));
  await waitFor(() => expect(screen.queryByText('Frontend CV')).not.toBeInTheDocument());
});
