/**
 * LayoutSelector Component Tests
 *
 * Tests for the LayoutSelector component that provides layout type selection.
 */

import React from 'react';
import { render, screen, fireEvent, within } from '@testing-library/react';
import '@testing-library/jest-dom';
import LayoutSelector from '../LayoutSelector';
import { LAYOUT_TYPES, LAYOUT_OPTIONS } from '../constants';

describe('LayoutSelector', () => {
  const defaultProps = {
    value: LAYOUT_TYPES.MODAL,
    onChange: jest.fn()
  };

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

  describe('Rendering', () => {
    it('renders without crashing', () => {
      const { container } = render(<LayoutSelector {...defaultProps} />);
      expect(container.querySelector('.layout-selector')).toBeInTheDocument();
    });

    it('renders all layout option labels', () => {
      render(<LayoutSelector {...defaultProps} />);

      expect(screen.getByText('Modal')).toBeInTheDocument();
      expect(screen.getByText('Top Banner')).toBeInTheDocument();
      expect(screen.getByText('Bottom Banner')).toBeInTheDocument();
      expect(screen.getByText('Fullscreen')).toBeInTheDocument();
    });

    it('renders with custom className', () => {
      const { container } = render(
        <LayoutSelector {...defaultProps} className="custom-layout-selector" />
      );

      const selector = container.querySelector('.layout-selector');
      expect(selector).toHaveClass('custom-layout-selector');
    });

    it('applies base layout-selector class', () => {
      const { container } = render(<LayoutSelector {...defaultProps} />);
      expect(container.querySelector('.layout-selector')).toBeInTheDocument();
    });

    it('renders radio group with proper structure', () => {
      const { container } = render(<LayoutSelector {...defaultProps} />);

      const radioGroup = container.querySelector('.layout-selector__radio-group');
      expect(radioGroup).toBeInTheDocument();
    });
  });

  describe('Value Selection', () => {
    it('renders with MODAL value by default', () => {
      render(<LayoutSelector onChange={defaultProps.onChange} />);

      // Component should render without error
      expect(screen.getByText('Modal')).toBeInTheDocument();
    });

    it('accepts HEADER value', () => {
      const { container } = render(
        <LayoutSelector value={LAYOUT_TYPES.HEADER} onChange={defaultProps.onChange} />
      );

      expect(container.querySelector('.layout-selector')).toBeInTheDocument();
    });

    it('accepts FOOTER value', () => {
      const { container } = render(
        <LayoutSelector value={LAYOUT_TYPES.FOOTER} onChange={defaultProps.onChange} />
      );

      expect(container.querySelector('.layout-selector')).toBeInTheDocument();
    });

    it('accepts FULLSCREEN value', () => {
      const { container } = render(
        <LayoutSelector value={LAYOUT_TYPES.FULLSCREEN} onChange={defaultProps.onChange} />
      );

      expect(container.querySelector('.layout-selector')).toBeInTheDocument();
    });
  });

  describe('User Interactions', () => {
    it('calls onChange when a radio button is clicked', () => {
      const handleChange = jest.fn();
      const { container } = render(
        <LayoutSelector value={LAYOUT_TYPES.MODAL} onChange={handleChange} />
      );

      // Find all radio inputs in the component
      const radioInputs = container.querySelectorAll('input[type="radio"]');

      // Should have 4 radio buttons (one for each layout type)
      expect(radioInputs.length).toBe(4);

      // Click the second radio button (Header/Top Banner)
      if (radioInputs[1]) {
        fireEvent.click(radioInputs[1]);
        expect(handleChange).toHaveBeenCalled();
      }
    });

    it('handles missing onChange gracefully', () => {
      // Should not throw error when onChange is not provided
      expect(() => {
        render(<LayoutSelector value={LAYOUT_TYPES.MODAL} />);
      }).not.toThrow();
    });
  });

  describe('Layout Options', () => {
    it('renders correct number of options', () => {
      const { container } = render(<LayoutSelector {...defaultProps} />);

      // Should render 4 layout options
      const radioInputs = container.querySelectorAll('input[type="radio"]');
      expect(radioInputs.length).toBe(LAYOUT_OPTIONS.length);
    });

    it('renders each layout option label', () => {
      render(<LayoutSelector {...defaultProps} />);

      LAYOUT_OPTIONS.forEach(option => {
        expect(screen.getByText(option.label)).toBeInTheDocument();
      });
    });
  });

  describe('CSS Classes', () => {
    it('applies radio group class', () => {
      const { container } = render(<LayoutSelector {...defaultProps} />);

      const radioGroup = container.querySelector('.layout-selector__radio-group');
      expect(radioGroup).toBeInTheDocument();
    });

    it('combines custom className with base class', () => {
      const { container } = render(
        <LayoutSelector {...defaultProps} className="my-custom-class" />
      );

      const selector = container.querySelector('.layout-selector');
      expect(selector).toHaveClass('layout-selector');
      expect(selector).toHaveClass('my-custom-class');
    });
  });

  describe('Props Spreading', () => {
    it('spreads additional props to container', () => {
      const { container } = render(
        <LayoutSelector
          {...defaultProps}
          data-custom-attr="test-value"
          id="custom-id"
        />
      );

      const selector = container.querySelector('.layout-selector');
      expect(selector).toHaveAttribute('data-custom-attr', 'test-value');
      expect(selector).toHaveAttribute('id', 'custom-id');
    });
  });

  describe('PropTypes Validation', () => {
    it('accepts all valid layout type values', () => {
      const validValues = Object.values(LAYOUT_TYPES);

      validValues.forEach(value => {
        expect(() => {
          render(<LayoutSelector value={value} onChange={defaultProps.onChange} />);
        }).not.toThrow();
      });
    });

    it('accepts all valid size values', () => {
      const validSizes = ['small', 'middle', 'large'];

      validSizes.forEach(size => {
        expect(() => {
          render(<LayoutSelector {...defaultProps} size={size} />);
        }).not.toThrow();
      });
    });
  });

  describe('Integration', () => {
    it('maintains structure across re-renders', () => {
      const { container, rerender } = render(
        <LayoutSelector value={LAYOUT_TYPES.MODAL} onChange={defaultProps.onChange} />
      );

      expect(container.querySelector('.layout-selector')).toBeInTheDocument();

      rerender(<LayoutSelector value={LAYOUT_TYPES.HEADER} onChange={defaultProps.onChange} />);
      expect(container.querySelector('.layout-selector')).toBeInTheDocument();

      rerender(<LayoutSelector value={LAYOUT_TYPES.FULLSCREEN} onChange={defaultProps.onChange} />);
      expect(container.querySelector('.layout-selector')).toBeInTheDocument();
    });

    it('works with controlled component pattern', () => {
      const ControlledComponent = () => {
        const [value, setValue] = React.useState(LAYOUT_TYPES.MODAL);

        return (
          <div>
            <div data-testid="current-value">{value}</div>
            <LayoutSelector value={value} onChange={setValue} />
          </div>
        );
      };

      render(<ControlledComponent />);

      expect(screen.getByTestId('current-value')).toHaveTextContent(LAYOUT_TYPES.MODAL);
      expect(screen.getByText('Modal')).toBeInTheDocument();
    });
  });

  describe('Component Structure', () => {
    it('renders with proper DOM hierarchy', () => {
      const { container } = render(<LayoutSelector {...defaultProps} />);

      const selector = container.querySelector('.layout-selector');
      expect(selector).toBeInTheDocument();

      const radioGroup = selector.querySelector('.layout-selector__radio-group');
      expect(radioGroup).toBeInTheDocument();
    });

    it('contains radio inputs', () => {
      const { container } = render(<LayoutSelector {...defaultProps} />);

      const radioInputs = container.querySelectorAll('input[type="radio"]');
      expect(radioInputs.length).toBeGreaterThan(0);
    });
  });
});
