import { render, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { ApolloProvider, InMemoryCache, ApolloClient, ApolloLink } from '@apollo/client';
import { CartProvider } from '@repo/kraken-ui';
import Product from '../app/product/page';

const mockClient = new ApolloClient({
  cache: new InMemoryCache(),
  link: new ApolloLink(() => null),
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'no-cache',
    },
    query: {
      fetchPolicy: 'no-cache',
    },
  },
});

jest.mock('@repo/graphql-types', () => ({
  useProductQuery: () => ({
    data: {
      Product: {
        id: '1',
        name: 'Energy saving light bulb',
        power: '25W',
        description: 'Available in 7 watts, 9 watts, 11 watts Spiral Light bulb...',
        price: 1299,
        quantity: 4,
        brand: 'Philips',
        weight: 77,
        height: 12.6,
        width: 6.2,
        length: 6.2,
        model_code: 'E27 ES',
        colour: 'Cool daylight',
        img_url: 'https://i.ibb.co/2nzwxnQ/bulb.png',
      },
    },
    loading: false,
    error: undefined,
  }),
}));

const renderWithProviders = (component: React.ReactElement) => {
  return render(
    <ApolloProvider client={mockClient}>
      <CartProvider>{component}</CartProvider>
    </ApolloProvider>
  );
};

/**
 * Product Component Extended Tests
 * Additional tests for edge cases and UI rendering
 */

test('should not decrease quantity below 1', async () => {
  const { getByText, getByTitle } = renderWithProviders(<Product />);

  await waitFor(() => {
    expect(getByText('Energy saving light bulb')).toBeInTheDocument();
  });

  const decreaseQuantity = getByText('-');
  const currentQuantity = getByTitle('Current quantity');

  expect(currentQuantity).toHaveTextContent('1');

  fireEvent.click(decreaseQuantity);
  expect(currentQuantity).toHaveTextContent('1');
});

test('should reset quantity to 1 after adding to cart', async () => {
  const { getByText, getByTitle } = renderWithProviders(<Product />);

  await waitFor(() => {
    expect(getByText('Energy saving light bulb')).toBeInTheDocument();
  });

  const increaseQuantity = getByText('+');
  const currentQuantity = getByTitle('Current quantity');
  const addToBasketElement = getByText('Add to cart');

  fireEvent.click(increaseQuantity);
  fireEvent.click(increaseQuantity);
  expect(currentQuantity).toHaveTextContent('3');

  fireEvent.click(addToBasketElement);
  expect(currentQuantity).toHaveTextContent('1');
});

test('should display product information correctly', async () => {
  const { getByText } = renderWithProviders(<Product />);

  await waitFor(() => {
    expect(getByText('Energy saving light bulb')).toBeInTheDocument();
  });

  expect(getByText('25W // Packet of 4')).toBeInTheDocument();
  expect(getByText('£12.99')).toBeInTheDocument();
  expect(getByText('Description')).toBeInTheDocument();
  expect(getByText(/Available in 7 watts/)).toBeInTheDocument();
});

test('should display product specifications', async () => {
  const { getByText } = renderWithProviders(<Product />);

  await waitFor(() => {
    expect(getByText('Energy saving light bulb')).toBeInTheDocument();
  });

  expect(getByText('Specifications')).toBeInTheDocument();
  expect(getByText('Brand')).toBeInTheDocument();
  expect(getByText('Philips')).toBeInTheDocument();
  expect(getByText('Item weight (g)')).toBeInTheDocument();
  expect(getByText('77')).toBeInTheDocument();
  expect(getByText('Colour')).toBeInTheDocument();
  expect(getByText('Cool daylight')).toBeInTheDocument();
});

test('should toggle cart popover when basket is clicked', async () => {
  const { getByText, getByAltText, queryByText } = renderWithProviders(<Product />);

  await waitFor(() => {
    expect(getByText('Energy saving light bulb')).toBeInTheDocument();
  });

  const basketButton = getByAltText('Basket').closest('button');

  // Cart should not be visible initially
  expect(queryByText('Your Cart')).not.toBeInTheDocument();

  // Click to open cart
  if (basketButton) fireEvent.click(basketButton);
  await waitFor(() => {
    expect(getByText('Your Cart')).toBeInTheDocument();
  });

  // Click to close cart
  if (basketButton) fireEvent.click(basketButton);
  await waitFor(() => {
    expect(queryByText('Your Cart')).not.toBeInTheDocument();
  });
});
