import { clsx } from 'clsx';
import { MouseEvent, forwardRef, HTMLAttributes, ReactNode, ElementType } from 'react';

import Body from '../../body';
import { LinkProps } from '../commonProps';

export interface BaseOptionProps extends Omit<HTMLAttributes<HTMLElement>, 'title' | 'content'> {
  'aria-label'?: string;
  'aria-expanded'?: boolean;
  'aria-controls'?: string;
  media?: ReactNode;
  name?: string;
  htmlFor?: string;
  title: ReactNode;
  content?: ReactNode;
  onClick?: (event: MouseEvent<HTMLElement>) => void;
  as?: ElementType;
  disabled?: boolean;
  button?: ReactNode;
  decision?: boolean;
  complex?: boolean;
  inverseMediaCircle?: boolean;
  className?: string;
  showMediaAtAllSizes?: boolean;
  showMediaCircle?: boolean;
  isContainerAligned?: boolean;
}

interface AnchorOptionProps extends BaseOptionProps, LinkProps {
  as: 'a';
}

export type OptionProps = BaseOptionProps | AnchorOptionProps;

export type ReferenceType = HTMLElement | HTMLAnchorElement;

const Option = forwardRef<ReferenceType, OptionProps>(
  (
    {
      media = '',
      title,
      content,
      as: component,
      button,
      decision = true,
      disabled = false,
      complex,
      inverseMediaCircle = true,
      className,
      showMediaAtAllSizes,
      showMediaCircle = true,
      isContainerAligned = false,
      ...rest
    },
    reference,
  ) => {
    const Element = component ?? 'label';

    return (
      <Element
        {...rest}
        ref={reference}
        className={clsx('np-option', className, {
          'decision-complex': complex,
          decision,
          disabled,
          'np-option__sm-media': showMediaAtAllSizes,
          'np-option__container-aligned': isContainerAligned,
        })}
        disabled={disabled && Element === 'button'}
      >
        <div className="media">
          {media && (
            <div className="media-left">
              {showMediaCircle ? (
                <div
                  className={clsx('circle circle-sm text-primary', {
                    'circle-inverse': inverseMediaCircle,
                  })}
                >
                  {media}
                </div>
              ) : (
                <div className="np-option__no-media-circle">{media}</div>
              )}
            </div>
          )}
          <div className="media-body">
            <h4 className="np-text-body-large-bold text-primary np-option__title">{title}</h4>
            {content && <Body className="d-block np-option__body">{content}</Body>}
          </div>
          <div className="media-right">{button}</div>
        </div>
      </Element>
    );
  },
);

export default Option;
