import React from 'react';
import {
  render, screen, fireEvent,
} from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import PropTypes from 'prop-types';
import LeftPanelContent from '../LeftPanelContent';

// Mock the CustomerSearchSection component
jest.mock('../../CustomerSearchSection', () => {
  // eslint-disable-next-line react/prop-types
  const MockCustomerSearchSection = ({ onCustomerSelect, onSearch, onClearSelection }) => (
    <div data-testid="customer-search-section">
      <button type="button" onClick={() => onCustomerSelect({ id: 1, name: 'Test Customer' })}>
        Select Customer
      </button>
      <button type="button" onClick={() => onSearch('test')}>Search</button>
      <button type="button" onClick={onClearSelection}>Clear Selection</button>
    </div>
  );
  return MockCustomerSearchSection;
});

// Mock messages for testing
const mockMessages = {
  extractingTags: { id: 'extractingTags', defaultMessage: 'Extracting tags...' },
  customerSearchTitle: { id: 'customerSearchTitle', defaultMessage: 'Customer' },
  enterCustomValuesForTags: { id: 'enterCustomValuesForTags', defaultMessage: 'Enter custom values for tags' },
  noTagsExtracted: { id: 'noTagsExtracted', defaultMessage: 'There are no personalization tags in this message, you can directly send out a test message' },
};

// Test wrapper with IntlProvider
const TestWrapper = ({ children, locale = 'en' }) => (
  <IntlProvider locale={locale} messages={mockMessages}>
    {children}
  </IntlProvider>
);

TestWrapper.propTypes = {
  children: PropTypes.node.isRequired,
  locale: PropTypes.string,
};

TestWrapper.defaultProps = {
  locale: 'en',
};

// Default props for testing
const defaultProps = {
  isExtractingTags: false,
  extractedTags: [
    { name: 'user', fullPath: 'user.name' },
    { name: 'email', fullPath: 'user.email' },
  ],
  selectedCustomer: null,
  handleCustomerSelect: jest.fn(),
  handleSearchCustomer: jest.fn(),
  customers: [
    { id: 1, name: 'John Doe', email: 'john@example.com' },
    { id: 2, name: 'Jane Smith', email: 'jane@example.com' },
  ],
  isSearchingCustomer: false,
  handleClearSelection: jest.fn(),
  tagsExtracted: false,
  handleExtractTags: jest.fn(),
  renderCustomValuesEditor: jest.fn(() => <div data-testid="custom-values-editor">Custom Values Editor</div>),
};

describe('LeftPanelContent', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('Loading State', () => {
    it('should render loading spinner when extracting tags', () => {
      const { container } = render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} isExtractingTags />
        </TestWrapper>
      );

      expect(screen.getByText('Extracting tags...')).toBeTruthy();
      expect(container.querySelector('.ant-spin')).toBeTruthy();
      expect(container.querySelector('.loading-container')).toBeTruthy();
    });

    it('should not render other content when extracting tags', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} isExtractingTags />
        </TestWrapper>
      );

      expect(screen.queryByTestId('customer-search-section')).toBeNull();
      expect(screen.queryByText('Enter custom values for tags')).toBeNull();
      expect(screen.queryByText('No personalization tags found in the template')).toBeNull();
    });
  });

  describe('Main Content with Extracted Tags', () => {
    it('should render customer search section when tags are extracted', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} />
        </TestWrapper>
      );

      expect(screen.getByText('Customer')).toBeTruthy();
      expect(screen.getByTestId('customer-search-section')).toBeTruthy();
    });

    it('should render extract tags button when tags not yet extracted', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted={false} />
        </TestWrapper>
      );

      expect(screen.getByText('Enter custom values for tags')).toBeTruthy();
      expect(screen.getByRole('button', { name: /enter custom values for tags/i })).toBeTruthy();
    });

    it('should not render extract tags button when tags are already extracted', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted />
        </TestWrapper>
      );

      expect(screen.queryByText('Enter custom values for tags')).toBeNull();
    });

    it('should render custom values editor when tags are extracted', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted />
        </TestWrapper>
      );

      // Check that renderCustomValuesEditor function is called
      expect(defaultProps.renderCustomValuesEditor).toHaveBeenCalled();
      // Since the actual rendering depends on what renderCustomValuesEditor returns,
      // we verify the function was called which means the condition was met
      expect(screen.getByTestId('customer-search-section')).toBeTruthy();
    });

    it('should not render custom values editor when tags are not extracted', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted={false} />
        </TestWrapper>
      );

      expect(screen.queryByTestId('custom-values-editor')).toBeNull();
      expect(defaultProps.renderCustomValuesEditor).not.toHaveBeenCalled();
    });
  });

  describe('No Tags State', () => {
    it('should render info note when no tags are extracted', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} extractedTags={[]} />
        </TestWrapper>
      );

      expect(screen.getByText('There are no personalization tags in this message, you can directly send out a test message')).toBeTruthy();
      expect(screen.queryByTestId('customer-search-section')).toBeNull();
      expect(screen.queryByText('Enter custom values for tags')).toBeNull();
    });

    it('should not render customer search or other content when no tags', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} extractedTags={[]} />
        </TestWrapper>
      );

      expect(screen.queryByText('Customer Search')).toBeNull();
      expect(screen.queryByTestId('customer-search-section')).toBeNull();
      expect(screen.queryByTestId('custom-values-editor')).toBeNull();
    });
  });

  describe('Customer Search Interactions', () => {
    it('should call handleCustomerSelect when customer is selected', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} />
        </TestWrapper>
      );

      const selectButton = screen.getByText('Select Customer');
      fireEvent.click(selectButton);

      expect(defaultProps.handleCustomerSelect).toHaveBeenCalledWith({ id: 1, name: 'Test Customer' });
    });

    it('should call handleSearchCustomer when search is performed', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} />
        </TestWrapper>
      );

      const searchButton = screen.getByText('Search');
      fireEvent.click(searchButton);

      expect(defaultProps.handleSearchCustomer).toHaveBeenCalledWith('test');
    });

    it('should call handleClearSelection when clear is clicked', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} />
        </TestWrapper>
      );

      const clearButton = screen.getByText('Clear Selection');
      fireEvent.click(clearButton);

      expect(defaultProps.handleClearSelection).toHaveBeenCalled();
    });
  });

  describe('Tags Extraction', () => {
    it('should call handleExtractTags when extract tags button is clicked', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted={false} />
        </TestWrapper>
      );

      const extractButton = screen.getByText('Enter custom values for tags');
      fireEvent.click(extractButton);

      expect(defaultProps.handleExtractTags).toHaveBeenCalled();
    });

    it('should have proper button styling for extract tags button', () => {
      const { container } = render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted={false} />
        </TestWrapper>
      );

      const buttonContainer = container.querySelector('.extract-tags-button');
      expect(buttonContainer).toBeTruthy();
    });
  });

  describe('Component Structure', () => {
    it('should have proper CSS classes for sections', () => {
      const { container } = render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} />
        </TestWrapper>
      );

      expect(container.querySelector('.panel-section.customer-section')).toBeTruthy();
      expect(container.querySelector('.panel-section')).toBeTruthy();
    });

    it('should render sections in correct order', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted={false} />
        </TestWrapper>
      );

      const customerTitle = screen.getByText('Customer');
      const extractButton = screen.getByText('Enter custom values for tags');

      // Customer search should appear before extract tags button
      expect(customerTitle.compareDocumentPosition(extractButton)).toBe(Node.DOCUMENT_POSITION_FOLLOWING);
    });
  });

  describe('Props Validation', () => {
    it('should handle selectedCustomer prop correctly', () => {
      const selectedCustomer = { id: 1, name: 'John Doe', email: 'john@example.com' };

      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} selectedCustomer={selectedCustomer} />
        </TestWrapper>
      );

      // Component should render without errors with selectedCustomer
      expect(screen.getByTestId('customer-search-section')).toBeTruthy();
    });

    it('should handle isSearchingCustomer prop correctly', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} isSearchingCustomer />
        </TestWrapper>
      );

      // Component should render without errors with isSearchingCustomer true
      expect(screen.getByTestId('customer-search-section')).toBeTruthy();
    });

    it('should accept all required props without warnings', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} />
        </TestWrapper>
      );

      expect(consoleSpy).not.toHaveBeenCalled();
      consoleSpy.mockRestore();
    });
  });

  describe('Edge Cases', () => {
    it('should handle empty customers array', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} customers={[]} />
        </TestWrapper>
      );

      expect(screen.getByTestId('customer-search-section')).toBeTruthy();
    });

    it('should handle single tag in extractedTags', () => {
      const singleTag = [{ name: 'user', fullPath: 'user.name' }];

      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} extractedTags={singleTag} />
        </TestWrapper>
      );

      expect(screen.getByText('Customer')).toBeTruthy();
      expect(screen.getByText('Enter custom values for tags')).toBeTruthy();
    });

    it('should handle null extractedTags gracefully', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} extractedTags={null} />
        </TestWrapper>
      );

      expect(screen.getByText('There are no personalization tags in this message, you can directly send out a test message')).toBeTruthy();
    });

    it('should handle renderCustomValuesEditor returning null', () => {
      const nullRenderer = jest.fn(() => null);

      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted renderCustomValuesEditor={nullRenderer} />
        </TestWrapper>
      );

      expect(nullRenderer).toHaveBeenCalled();
      expect(screen.queryByTestId('custom-values-editor')).toBeNull();
    });
  });

  describe('Accessibility', () => {
    it('should have proper heading structure', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} />
        </TestWrapper>
      );

      // CapHeader should render the customer search title
      expect(screen.getByText('Customer')).toBeTruthy();
    });

    it('should have proper button roles', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} tagsExtracted={false} />
        </TestWrapper>
      );

      const buttons = screen.getAllByRole('button');
      expect(buttons.length).toBeGreaterThan(0);
    });

    it('should have informative text for no tags state', () => {
      render(
        <TestWrapper>
          <LeftPanelContent {...defaultProps} extractedTags={[]} />
        </TestWrapper>
      );

      const infoText = screen.getByText('There are no personalization tags in this message, you can directly send out a test message');
      expect(infoText).toBeTruthy();
    });
  });
});
