import React from 'react';
import { render, screen } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { CartPopover } from '../CartPopover';
import { CartProvider } from '../../contexts/CartContext';

const mockOnClose = jest.fn();

interface MockCartItem {
  id: string;
  name: string;
  price: number;
  image: string;
  quantity: number;
}

const renderWithCartProvider = (ui: React.ReactElement, initialItems: MockCartItem[] = []) => {
  // Mock localStorage
  const localStorageMock = {
    getItem: jest.fn(() => JSON.stringify(initialItems)),
    setItem: jest.fn(),
    removeItem: jest.fn(),
    clear: jest.fn(),
  };
  Object.defineProperty(window, 'localStorage', {
    value: localStorageMock,
    writable: true,
  });

  return render(<CartProvider>{ui}</CartProvider>);
};

describe('CartPopover', () => {
  beforeEach(() => {
    mockOnClose.mockClear();
  });

  it('does not render when isOpen is false', () => {
    renderWithCartProvider(<CartPopover isOpen={false} onClose={mockOnClose} />);
    expect(screen.queryByText('Your Cart')).not.toBeInTheDocument();
  });

  it('renders when isOpen is true', () => {
    renderWithCartProvider(<CartPopover isOpen={true} onClose={mockOnClose} />);
    expect(screen.getByText('Your Cart')).toBeInTheDocument();
  });

  it('displays empty cart message when cart is empty', () => {
    renderWithCartProvider(<CartPopover isOpen={true} onClose={mockOnClose} />);
    expect(screen.getByText('Your cart is empty')).toBeInTheDocument();
  });

  it('calls onClose when close button is clicked', async () => {
    const user = userEvent.setup();
    renderWithCartProvider(<CartPopover isOpen={true} onClose={mockOnClose} />);
    
    const closeButton = screen.getByLabelText('Close cart');
    await user.click(closeButton);
    
    expect(mockOnClose).toHaveBeenCalledTimes(1);
  });

  it('calls onClose when overlay is clicked', async () => {
    const user = userEvent.setup();
    const { container } = renderWithCartProvider(<CartPopover isOpen={true} onClose={mockOnClose} />);
    
    const overlay = container.querySelector('.overlay');
    if (overlay) {
      await user.click(overlay);
      expect(mockOnClose).toHaveBeenCalledTimes(1);
    }
  });

  it('displays cart items when items exist', () => {
    const mockItems = [
      {
        id: '1',
        name: 'Test Product',
        price: 1299,
        image: '/test.jpg',
        quantity: 2,
      },
    ];

    renderWithCartProvider(
      <CartPopover isOpen={true} onClose={mockOnClose} />,
      mockItems
    );

    expect(screen.getByText('Test Product')).toBeInTheDocument();
    expect(screen.getByText('£12.99')).toBeInTheDocument();
    expect(screen.getByText('2')).toBeInTheDocument();
  });

  it('displays total price', () => {
    const mockItems = [
      {
        id: '1',
        name: 'Product 1',
        price: 1000,
        image: '/test1.jpg',
        quantity: 2,
      },
      {
        id: '2',
        name: 'Product 2',
        price: 500,
        image: '/test2.jpg',
        quantity: 1,
      },
    ];

    renderWithCartProvider(
      <CartPopover isOpen={true} onClose={mockOnClose} />,
      mockItems
    );

    expect(screen.getByText('Total:')).toBeInTheDocument();
    expect(screen.getByText('£25.00')).toBeInTheDocument();
  });

  it('renders checkout button when items exist', () => {
    const mockItems = [
      {
        id: '1',
        name: 'Test Product',
        price: 1299,
        image: '/test.jpg',
        quantity: 1,
      },
    ];

    renderWithCartProvider(
      <CartPopover isOpen={true} onClose={mockOnClose} />,
      mockItems
    );

    expect(screen.getByText('Go to Checkout')).toBeInTheDocument();
  });

  it('does not render checkout button when cart is empty', () => {
    renderWithCartProvider(<CartPopover isOpen={true} onClose={mockOnClose} />);
    expect(screen.queryByText('Go to Checkout')).not.toBeInTheDocument();
  });

  it('displays remove button for each item', () => {
    const mockItems = [
      {
        id: '1',
        name: 'Test Product',
        price: 1299,
        image: '/test.jpg',
        quantity: 1,
      },
    ];

    renderWithCartProvider(
      <CartPopover isOpen={true} onClose={mockOnClose} />,
      mockItems
    );

    expect(screen.getByText('Remove')).toBeInTheDocument();
  });
});
