/* eslint-disable react/display-name */
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;
  additionalContent?: ReactNode;
}

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

export type OptionProps = BaseOptionProps | AnchorOptionProps;

export type ReferenceType = HTMLElement | HTMLAnchorElement;

/**
 * @deprecated Use `<ListItem />` instead (run codemod to migrate: **`npx @wise/wds-codemods@latest list-item`**).
 */
const Option = forwardRef<ReferenceType, OptionProps>(
  (
    {
      media = '',
      title,
      content,
      as: component,
      button,
      decision = true,
      disabled = false,
      complex,
      inverseMediaCircle = true,
      className,
      showMediaAtAllSizes,
      showMediaCircle = true,
      isContainerAligned = false,
      additionalContent,
      ...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={clsx('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">
            {/* @ts-expect-error div can have role and aria-lavel props */}
            <Body
              type="body-large-bold"
              // for a11y this needs to be a header but for SEO it shouldn't be `h*` tag
              // so we enable header semantics via `role` and `aria-level` attrs
              role="heading"
              aria-level="4"
              className="text-primary np-option__title"
            >
              {title}
            </Body>
            {content && <Body className="d-block np-option__body">{content}</Body>}
          </div>
          <div className="media-right">{button}</div>
        </div>
        {additionalContent ? (
          <div className="np-option-additional-content">{additionalContent}</div>
        ) : null}
      </Element>
    );
  },
);

export default Option;
