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

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

// Mock the useProductQuery hook
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 Tests
 * 
 * Notes:
 * replaced render with renderWithProviders to include necessary context providers
 * added await waitFor - wait for Apollo hooks to complete - initial render, data arrival, component re-rendering
 */
test('should be able to increase and decrease product quantity', async () => {
  const { getByText, getByTitle } = renderWithProviders(<Product />);

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

  const increaseQuantity = getByText('+');
  const currentQuantity = getByTitle('Current quantity');
  
  expect(currentQuantity).toHaveTextContent('1');

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

  const decreaseQuantity = getByText('-');

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

test('should be able to add items to the basket', async () => {
  const { getByText, getByTitle } = renderWithProviders(<Product />);

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

  const increaseQuantity = getByText('+');

  const currentQuantity = getByTitle('Current quantity');

  fireEvent.click(increaseQuantity);
  fireEvent.click(increaseQuantity);
  fireEvent.click(increaseQuantity);

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

  const addToBasketElement = getByText('Add to cart');
  fireEvent.click(addToBasketElement);

  const basketItems = getByTitle('Basket items');
  expect(basketItems).toHaveTextContent('4');
});
