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

// Mock component for demonstration purposes
// This would normally import an actual component
const MockButton: React.FC<{
  onClick: () => void;
  children: React.ReactNode;
  disabled?: boolean;
}> = ({ onClick, children, disabled = false }) => (
  <button
    onClick={onClick}
    disabled={disabled}
    data-testid='mock-button'
    className={`btn ${disabled ? 'btn-disabled' : 'btn-primary'}`}
  >
    {children}
  </button>
);

const MockMedicationCard: React.FC<{
  medication: {
    id: string;
    name: string;
    dosage: string;
    frequency: string;
  };
  onEdit: (id: string) => void;
  onDelete: (id: string) => void;
}> = ({ medication, onEdit, onDelete }) => (
  <div data-testid='medication-card' className='medication-card'>
    <h3 data-testid='medication-name'>{medication.name}</h3>
    <p data-testid='medication-dosage'>Dosage: {medication.dosage}</p>
    <p data-testid='medication-frequency'>Frequency: {medication.frequency}</p>
    <div className='actions'>
      <MockButton onClick={() => onEdit(medication.id)}>Edit</MockButton>
      <MockButton onClick={() => onDelete(medication.id)}>Delete</MockButton>
    </div>
  </div>
);

describe('Component Testing Examples', () => {
  describe('MockButton Component', () => {
    test('renders button with correct text', () => {
      const mockClick = jest.fn();
      render(<MockButton onClick={mockClick}>Click Me</MockButton>);

      const button = screen.getByTestId('mock-button');
      expect(button).toBeInTheDocument();
      expect(button).toHaveTextContent('Click Me');
    });

    test('calls onClick handler when clicked', () => {
      const mockClick = jest.fn();
      render(<MockButton onClick={mockClick}>Click Me</MockButton>);

      const button = screen.getByTestId('mock-button');
      fireEvent.click(button);

      expect(mockClick).toHaveBeenCalledTimes(1);
    });

    test('applies disabled state correctly', () => {
      const mockClick = jest.fn();
      render(
        <MockButton onClick={mockClick} disabled>
          Disabled Button
        </MockButton>
      );

      const button = screen.getByTestId('mock-button');
      expect(button).toBeDisabled();
      expect(button).toHaveClass('btn-disabled');

      fireEvent.click(button);
      expect(mockClick).not.toHaveBeenCalled();
    });

    test('applies correct CSS classes', () => {
      const mockClick = jest.fn();
      const { rerender } = render(
        <MockButton onClick={mockClick}>Normal Button</MockButton>
      );

      let button = screen.getByTestId('mock-button');
      expect(button).toHaveClass('btn', 'btn-primary');
      expect(button).not.toHaveClass('btn-disabled');

      rerender(
        <MockButton onClick={mockClick} disabled>
          Disabled Button
        </MockButton>
      );

      button = screen.getByTestId('mock-button');
      expect(button).toHaveClass('btn', 'btn-disabled');
      expect(button).not.toHaveClass('btn-primary');
    });
  });

  describe('MockMedicationCard Component', () => {
    const mockMedication = {
      id: 'med-123',
      name: 'Aspirin',
      dosage: '100mg',
      frequency: 'Daily',
    };

    const defaultProps = {
      medication: mockMedication,
      onEdit: jest.fn(),
      onDelete: jest.fn(),
    };

    beforeEach(() => {
      jest.clearAllMocks();
    });

    test('renders medication information correctly', () => {
      render(<MockMedicationCard {...defaultProps} />);

      expect(screen.getByTestId('medication-card')).toBeInTheDocument();
      expect(screen.getByTestId('medication-name')).toHaveTextContent(
        'Aspirin'
      );
      expect(screen.getByTestId('medication-dosage')).toHaveTextContent(
        'Dosage: 100mg'
      );
      expect(screen.getByTestId('medication-frequency')).toHaveTextContent(
        'Frequency: Daily'
      );
    });

    test('renders action buttons', () => {
      render(<MockMedicationCard {...defaultProps} />);

      const editButton = screen.getByText('Edit');
      const deleteButton = screen.getByText('Delete');

      expect(editButton).toBeInTheDocument();
      expect(deleteButton).toBeInTheDocument();
    });

    test('calls onEdit with correct medication ID when edit button is clicked', () => {
      const mockOnEdit = jest.fn();
      render(<MockMedicationCard {...defaultProps} onEdit={mockOnEdit} />);

      const editButton = screen.getByText('Edit');
      fireEvent.click(editButton);

      expect(mockOnEdit).toHaveBeenCalledTimes(1);
      expect(mockOnEdit).toHaveBeenCalledWith('med-123');
    });

    test('calls onDelete with correct medication ID when delete button is clicked', () => {
      const mockOnDelete = jest.fn();
      render(<MockMedicationCard {...defaultProps} onDelete={mockOnDelete} />);

      const deleteButton = screen.getByText('Delete');
      fireEvent.click(deleteButton);

      expect(mockOnDelete).toHaveBeenCalledTimes(1);
      expect(mockOnDelete).toHaveBeenCalledWith('med-123');
    });

    test('handles different medication data', () => {
      const differentMedication = {
        id: 'med-456',
        name: 'Vitamin D',
        dosage: '1000 IU',
        frequency: 'Weekly',
      };

      render(
        <MockMedicationCard
          {...defaultProps}
          medication={differentMedication}
        />
      );

      expect(screen.getByTestId('medication-name')).toHaveTextContent(
        'Vitamin D'
      );
      expect(screen.getByTestId('medication-dosage')).toHaveTextContent(
        'Dosage: 1000 IU'
      );
      expect(screen.getByTestId('medication-frequency')).toHaveTextContent(
        'Frequency: Weekly'
      );
    });

    test('maintains proper component structure', () => {
      render(<MockMedicationCard {...defaultProps} />);

      const card = screen.getByTestId('medication-card');
      expect(card).toHaveClass('medication-card');

      const actionsContainer = card.querySelector('.actions');
      expect(actionsContainer).toBeInTheDocument();

      // Verify buttons are within the actions container
      const buttons = actionsContainer?.querySelectorAll('button');
      expect(buttons).toHaveLength(2);
    });
  });

  describe('Component Integration Tests', () => {
    test('multiple components work together', () => {
      const medications = [
        {
          id: 'med-1',
          name: 'Aspirin',
          dosage: '100mg',
          frequency: 'Daily',
        },
        {
          id: 'med-2',
          name: 'Vitamin C',
          dosage: '500mg',
          frequency: 'Twice daily',
        },
      ];

      const MockMedicationList: React.FC<{
        medications: typeof medications;
        onEdit: (id: string) => void;
        onDelete: (id: string) => void;
      }> = ({ medications, onEdit, onDelete }) => (
        <div data-testid='medication-list'>
          {medications.map(med => (
            <MockMedicationCard
              key={med.id}
              medication={med}
              onEdit={onEdit}
              onDelete={onDelete}
            />
          ))}
        </div>
      );

      const mockOnEdit = jest.fn();
      const mockOnDelete = jest.fn();

      render(
        <MockMedicationList
          medications={medications}
          onEdit={mockOnEdit}
          onDelete={mockOnDelete}
        />
      );

      // Verify all medications are rendered
      expect(screen.getAllByTestId('medication-card')).toHaveLength(2);
      expect(screen.getByText('Aspirin')).toBeInTheDocument();
      expect(screen.getByText('Vitamin C')).toBeInTheDocument();

      // Test interaction with first medication
      const editButtons = screen.getAllByText('Edit');
      fireEvent.click(editButtons[0]);
      expect(mockOnEdit).toHaveBeenCalledWith('med-1');

      // Test interaction with second medication
      const deleteButtons = screen.getAllByText('Delete');
      fireEvent.click(deleteButtons[1]);
      expect(mockOnDelete).toHaveBeenCalledWith('med-2');
    });
  });

  describe('Accessibility Tests', () => {
    test('buttons have proper accessibility attributes', () => {
      const mockClick = jest.fn();
      render(<MockButton onClick={mockClick}>Accessible Button</MockButton>);

      const button = screen.getByRole('button');
      expect(button).toBeInTheDocument();
      expect(button).toHaveAccessibleName('Accessible Button');
    });

    test('medication card structure supports screen readers', () => {
      render(
        <MockMedicationCard
          {...{
            medication: {
              id: 'med-123',
              name: 'Test Medicine',
              dosage: '50mg',
              frequency: 'As needed',
            },
            onEdit: jest.fn(),
            onDelete: jest.fn(),
          }}
        />
      );

      // Check that important information is properly structured
      const heading = screen.getByRole('heading', { level: 3 });
      expect(heading).toHaveTextContent('Test Medicine');

      const editButton = screen.getByRole('button', { name: 'Edit' });
      const deleteButton = screen.getByRole('button', { name: 'Delete' });

      expect(editButton).toBeInTheDocument();
      expect(deleteButton).toBeInTheDocument();
    });
  });

  describe('Error Handling', () => {
    test('components handle missing props gracefully', () => {
      // Test with minimal props
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {
        // Mock implementation for testing
      });

      render(
        <MockMedicationCard
          medication={{
            id: '',
            name: '',
            dosage: '',
            frequency: '',
          }}
          onEdit={jest.fn()}
          onDelete={jest.fn()}
        />
      );

      // Component should still render even with empty data
      expect(screen.getByTestId('medication-card')).toBeInTheDocument();

      consoleSpy.mockRestore();
    });
  });
});
