import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from './Button.js';
import { BFUIProvider } from '../../BFUIProvider.js';

// Wrap component with BFUIProvider for Chakra UI theme context
const renderWithProvider = (ui: React.ReactElement) => {
  return render(<BFUIProvider>{ui}</BFUIProvider>);
};

describe('Button Component', () => {
  test('renders with children text', () => {
    renderWithProvider(<Button>Click Me</Button>);
    
    const button = screen.getByRole('button', { name: 'Click Me' });
    expect(button).toBeInTheDocument();
    expect(button).toHaveTextContent('Click Me');
  });
  
  test('renders with left icon', () => {
    const LeftIcon = () => <span data-testid="left-icon">🔍</span>;
    
    renderWithProvider(
      <Button leftIcon={<LeftIcon />}>
        Search
      </Button>
    );
    
    const button = screen.getByRole('button', { name: 'Search' });
    const icon = screen.getByTestId('left-icon');
    
    expect(button).toBeInTheDocument();
    expect(icon).toBeInTheDocument();
    expect(button).toContainElement(icon);
  });
  
  test('renders with right icon', () => {
    const RightIcon = () => <span data-testid="right-icon">➡️</span>;
    
    renderWithProvider(
      <Button rightIcon={<RightIcon />}>
        Next
      </Button>
    );
    
    const button = screen.getByRole('button', { name: 'Next' });
    const icon = screen.getByTestId('right-icon');
    
    expect(button).toBeInTheDocument();
    expect(icon).toBeInTheDocument();
    expect(button).toContainElement(icon);
  });
  
  test('handles click events', async () => {
    const handleClick = jest.fn();
    const user = userEvent.setup();
    
    renderWithProvider(
      <Button onClick={handleClick}>
        Click Me
      </Button>
    );
    
    const button = screen.getByRole('button', { name: 'Click Me' });
    await user.click(button);
    
    expect(handleClick).toHaveBeenCalledTimes(1);
  });
  
  test('renders in disabled state', async () => {
    const handleClick = jest.fn();
    const user = userEvent.setup();
    
    renderWithProvider(
      <Button isDisabled onClick={handleClick}>
        Disabled Button
      </Button>
    );
    
    const button = screen.getByRole('button', { name: 'Disabled Button' });
    
    expect(button).toBeDisabled();
    
    await user.click(button);
    expect(handleClick).not.toHaveBeenCalled();
  });
  
  test('renders in loading state', () => {
    renderWithProvider(
      <Button isLoading loadingText="Loading...">
        Submit
      </Button>
    );
    
    const button = screen.getByRole('button', { name: 'Loading...' });
    expect(button).toHaveAttribute('data-loading');
  });
  
  test('renders with custom variants', () => {
    const { rerender } = renderWithProvider(
      <Button variant="outline">
        Outline Button
      </Button>
    );
    
    const outlineButton = screen.getByRole('button', { name: 'Outline Button' });
    expect(outlineButton).toBeInTheDocument();
    
    rerender(
      <BFUIProvider>
        <Button variant="ghost">
          Ghost Button
        </Button>
      </BFUIProvider>
    );
    
    const ghostButton = screen.getByRole('button', { name: 'Ghost Button' });
    expect(ghostButton).toBeInTheDocument();
    
    rerender(
      <BFUIProvider>
        <Button variant="link">
          Link Button
        </Button>
      </BFUIProvider>
    );
    
    const linkButton = screen.getByRole('button', { name: 'Link Button' });
    expect(linkButton).toBeInTheDocument();
  });
  
  test('renders with different sizes', () => {
    const { rerender } = renderWithProvider(
      <Button size="sm">
        Small Button
      </Button>
    );
    
    const smallButton = screen.getByRole('button', { name: 'Small Button' });
    expect(smallButton).toBeInTheDocument();
    
    rerender(
      <BFUIProvider>
        <Button size="lg">
          Large Button
        </Button>
      </BFUIProvider>
    );
    
    const largeButton = screen.getByRole('button', { name: 'Large Button' });
    expect(largeButton).toBeInTheDocument();
  });
  
  test('renders with custom color scheme', () => {
    renderWithProvider(
      <Button colorScheme="red">
        Danger Button
      </Button>
    );
    
    const dangerButton = screen.getByRole('button', { name: 'Danger Button' });
    expect(dangerButton).toBeInTheDocument();
  });
  
  test('renders as full width', () => {
    renderWithProvider(
      <Button isFullWidth>
        Full Width Button
      </Button>
    );
    
    const fullWidthButton = screen.getByRole('button', { name: 'Full Width Button' });
    expect(fullWidthButton).toHaveStyle({ width: '100%' });
  });
  
  test('maps custom variants to Chakra variants', () => {
    const { rerender } = renderWithProvider(
      <Button variant="primary">
        Primary Button
      </Button>
    );
    
    const primaryButton = screen.getByRole('button', { name: 'Primary Button' });
    expect(primaryButton).toBeInTheDocument();
    
    rerender(
      <BFUIProvider>
        <Button variant="secondary">
          Secondary Button
        </Button>
      </BFUIProvider>
    );
    
    const secondaryButton = screen.getByRole('button', { name: 'Secondary Button' });
    expect(secondaryButton).toBeInTheDocument();
    
    rerender(
      <BFUIProvider>
        <Button variant="danger">
          Danger Button
        </Button>
      </BFUIProvider>
    );
    
    const dangerButton = screen.getByRole('button', { name: 'Danger Button' });
    expect(dangerButton).toBeInTheDocument();
  });
  
  test('renders with custom class name', () => {
    renderWithProvider(
      <Button className="custom-button-class">
        Custom Class Button
      </Button>
    );
    
    const button = screen.getByRole('button', { name: 'Custom Class Button' });
    expect(button).toHaveClass('custom-button-class');
  });
  
  test('renders with aria-label', () => {
    renderWithProvider(
      <Button aria-label="Close modal">
        X
      </Button>
    );
    
    const button = screen.getByRole('button', { name: 'Close modal' });
    expect(button).toBeInTheDocument();
  });
  
  test('forwards data-testid attribute', () => {
    renderWithProvider(
      <Button data-testid="submit-button">
        Submit
      </Button>
    );
    
    const button = screen.getByTestId('submit-button');
    expect(button).toBeInTheDocument();
    expect(button).toHaveTextContent('Submit');
  });
});