import React, { useCallback, useMemo } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import CapRow from '@capillarytech/cap-ui-library/CapRow';
import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
import CapSelect from '@capillarytech/cap-ui-library/CapSelect';
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
import { LAYOUT_MODE, SELECT_WIDTH, STATE_OPTIONS } from './constants';
import { getBrowserOptionsForOS, getSupportedStates } from './config/notificationMappings';
import messages from '../messages';
import './preview.scss';

const getDropdownPopupContainer = (triggerNode) =>
  triggerNode.closest('.ant-modal-container, .ant-modal-content') || document.body;

/**
 * PreviewControls Component
 * 
 * Renders dropdown controls for selecting Operating System, Browser, and State
 * for the web push notification preview.
 * 
 * Implements cascading dropdown reset behavior:
 * - When OS changes, Browser and State reset to first available option
 * - When Browser changes, State resets to first available option
 * 
 * @param {string} layoutMode - 'inline', 'newRow', or 'compact' (default: 'newRow')
 * @param {boolean} showStateDropdown - Whether to show the State dropdown (default: true)
 * @param {boolean|function} stateDropdownDisabled - Controls State dropdown disabled state.
 *   - If boolean: directly sets disabled state
 *   - If function: receives (selectedOS, selectedBrowser, stateOptions) and returns boolean
 *   - Note: Can be extended to accept object { disabled: boolean, tooltip?: string } for tooltip support
 */
const PreviewControls = ({
  selectedOS,
  selectedBrowser,
  selectedState,
  osOptions,
  browserOptions,
  stateOptions,
  onOSChange,
  onBrowserChange,
  onStateChange,
  layoutMode = LAYOUT_MODE.NEW_ROW,
  showStateDropdown = true,
  stateDropdownDisabled = false,
}) => {
  const selectWidth = layoutMode === LAYOUT_MODE.COMPACT ? SELECT_WIDTH.COMPACT : SELECT_WIDTH.FULL;

  // Determine if State dropdown should be disabled
  // Supports boolean or function for extensibility
  // Note: Can be extended to support object { disabled: boolean, tooltip?: string } for tooltip messages
  const isStateDropdownDisabled = useMemo(() => {
    // Disable State dropdown for Windows (only Collapsed state is supported)
    if (selectedOS === 'Windows') {
      return true;
    }
    return typeof stateDropdownDisabled === 'function'
      ? stateDropdownDisabled(selectedOS, selectedBrowser, stateOptions)
      : stateDropdownDisabled;
  }, [stateDropdownDisabled, selectedOS, selectedBrowser, stateOptions]);

  // Memoized State dropdown content to avoid recreating on every render
  const stateDropdownContent = useMemo(() => (
    <>
      <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
        <FormattedMessage {...messages.state} />
      </CapLabel>
      <CapSelect.CapCustomSelect
        width={selectWidth}
        options={stateOptions}
        value={selectedState}
        onChange={onStateChange}
        getPopupContainer={getDropdownPopupContainer}
        // Note: Add tooltip prop here when tooltip mechanism is implemented
        // tooltip={tooltipMessage ? tooltipMessage : undefined}
      />
    </>
  ), [selectWidth, stateOptions, selectedState, onStateChange]);

  // Memoized State dropdown renderer with disabled wrapper
  const renderStateDropdown = useMemo(() => {
    if (isStateDropdownDisabled) {
      return (
        <div className="preview-control-disabled-wrapper">
          {stateDropdownContent}
        </div>
      );
    }
    return stateDropdownContent;
  }, [isStateDropdownDisabled, stateDropdownContent]);

  /**
   * Cascading dropdown reset handler for OS changes
   * Resets Browser and State to first available option when OS changes
   * 
   * This implements cascading dropdown behavior: when a parent dropdown (OS) changes,
   * dependent dropdowns (Browser, State) reset to their first available option.
   */
  const handleOSChangeWithCascade = useCallback((value) => {
    onOSChange(value);
    
    // Get browser options for the new OS to ensure we reset to a valid option
    const newBrowserOptions = getBrowserOptionsForOS(value);
    
    // Reset Browser to first available option for the new OS
    const newBrowserValue = newBrowserOptions && newBrowserOptions.length > 0 
      ? newBrowserOptions[0].value 
      : null;
    
    if (newBrowserValue && onBrowserChange) {
      onBrowserChange(newBrowserValue);
    }
    
    // Compute fresh state options based on new OS and Browser combination
    // Only reset state if stateOptions is provided and not empty
    if (showStateDropdown && newBrowserValue && onStateChange && stateOptions && stateOptions.length > 0) {
      // For Windows, always reset to "Collapsed" (only supported state)
      if (value === 'Windows') {
        onStateChange('Collapsed');
      } else {
        const newSupportedStates = getSupportedStates(value, newBrowserValue);
        const newStateOptions = newSupportedStates.length > 0
          ? newSupportedStates.map((state) => ({ value: state, label: state }))
          : STATE_OPTIONS;
        
        if (newStateOptions.length > 0) {
          onStateChange(newStateOptions[0].value);
        }
      }
    }
  }, [onOSChange, onBrowserChange, onStateChange, stateOptions, showStateDropdown]);

  /**
   * Cascading dropdown reset handler for Browser changes
   * Resets State to first available option when Browser changes
   */
  const handleBrowserChangeWithCascade = useCallback((value) => {
    onBrowserChange(value);
    
    // Compute fresh state options based on current OS and new Browser combination
    // Only reset state if stateOptions is provided and not empty
    if (showStateDropdown && onStateChange && stateOptions && stateOptions.length > 0) {
      const newSupportedStates = getSupportedStates(selectedOS, value);
      const newStateOptions = newSupportedStates.length > 0
        ? newSupportedStates.map((state) => ({ value: state, label: state }))
        : STATE_OPTIONS;
      
      if (newStateOptions.length > 0) {
        onStateChange(newStateOptions[0].value);
      }
    }
  }, [onBrowserChange, onStateChange, selectedOS, stateOptions, showStateDropdown]);

  const controls = [
    {
      key: 'os',
      label: 'operatingSystem',
      value: selectedOS,
      options: osOptions,
      onChange: handleOSChangeWithCascade,
      className: 'preview-control-os',
    },
    {
      key: 'browser',
      label: 'browser',
      value: selectedBrowser,
      options: browserOptions,
      onChange: handleBrowserChangeWithCascade,
      className: 'preview-control-browser',
    },
  ];

  if (showStateDropdown) {
    controls.push({
      key: 'state',
      label: 'state',
      value: selectedState,
      options: stateOptions,
      onChange: onStateChange,
      className: 'preview-control-state',
      disabled: isStateDropdownDisabled,
    });
  }

  const renderControl = useCallback(({ key, label, value, options, onChange, className, disabled }) => {
    // Special handling for state dropdown - use memoized renderer
    if (key === 'state') {
      return (
        <div key={key} className={`preview-control ${className}`}>
          {renderStateDropdown}
        </div>
      );
    }

    const controlContent = (
      <>
        <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
          <FormattedMessage {...messages[label]} />
        </CapLabel>
        <CapSelect.CapCustomSelect
          width={selectWidth}
          options={options}
          value={value}
          onChange={onChange}
          getPopupContainer={getDropdownPopupContainer}
        />
      </>
    );

    return (
      <div key={key} className={`preview-control ${className}`}>
        {disabled ? (
          <div className="preview-control-disabled-wrapper">
            {controlContent}
          </div>
        ) : (
          controlContent
        )}
      </div>
    );
  }, [selectWidth, renderStateDropdown]);

  if (layoutMode === LAYOUT_MODE.COMPACT) {
    return (
      <div className="preview-controls preview-controls-compact">
        {controls.map(renderControl)}
      </div>
    );
  }

  return (
    <>
      <CapRow className="preview-controls">
        <CapColumn span={12} className="preview-control-os">
          <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
            <FormattedMessage {...messages.operatingSystem} />
          </CapLabel>
          <CapSelect.CapCustomSelect
            width={selectWidth}
            options={osOptions}
            value={selectedOS}
            onChange={handleOSChangeWithCascade}
            getPopupContainer={getDropdownPopupContainer}
          />
        </CapColumn>
        <CapColumn span={12} className="preview-control-browser">
          <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
            <FormattedMessage {...messages.browser} />
          </CapLabel>
          <CapSelect.CapCustomSelect
            width={selectWidth}
            options={browserOptions}
            value={selectedBrowser}
            onChange={handleBrowserChangeWithCascade}
            getPopupContainer={getDropdownPopupContainer}
          />
        </CapColumn>
      </CapRow>
      {showStateDropdown && layoutMode === LAYOUT_MODE.NEW_ROW && (
        <CapRow className="preview-controls-state">
          <CapColumn span={12} className="preview-control-state">
            {renderStateDropdown}
          </CapColumn>
        </CapRow>
      )}
      {showStateDropdown && layoutMode === LAYOUT_MODE.INLINE && (
        <CapRow className="preview-controls">
          <CapColumn span={12} className="preview-control-state">
            {renderStateDropdown}
          </CapColumn>
        </CapRow>
      )}
    </>
  );
};

PreviewControls.propTypes = {
  selectedOS: PropTypes.string.isRequired,
  selectedBrowser: PropTypes.string.isRequired,
  selectedState: PropTypes.string,
  osOptions: PropTypes.arrayOf(
    PropTypes.shape({
      value: PropTypes.string.isRequired,
      label: PropTypes.string.isRequired,
    }),
  ).isRequired,
  browserOptions: PropTypes.arrayOf(
    PropTypes.shape({
      value: PropTypes.string.isRequired,
      label: PropTypes.string.isRequired,
    }),
  ).isRequired,
  stateOptions: PropTypes.arrayOf(
    PropTypes.shape({
      value: PropTypes.string.isRequired,
      label: PropTypes.string.isRequired,
    }),
  ),
  onOSChange: PropTypes.func.isRequired,
  onBrowserChange: PropTypes.func.isRequired,
  onStateChange: PropTypes.func,
  layoutMode: PropTypes.oneOf([LAYOUT_MODE.INLINE, LAYOUT_MODE.NEW_ROW, LAYOUT_MODE.COMPACT]),
  showStateDropdown: PropTypes.bool,
  stateDropdownDisabled: PropTypes.oneOfType([
    PropTypes.bool,
    PropTypes.func, // (selectedOS, selectedBrowser, stateOptions) => boolean
    // Note: Can add PropTypes.shape({ disabled: PropTypes.bool, tooltip: PropTypes.string }) for tooltip support
  ]),
};

export default PreviewControls;

