import * as React from 'react';
import clsx from 'clsx';
import * as ButtonBase from '@tesseract-design/web-base-button';
import styles from './style.module.css';

export type ToggleButtonDerivedElement = HTMLInputElement;

export interface ToggleButtonProps extends Omit<React.InputHTMLAttributes<ToggleButtonDerivedElement>, 'type' | 'size'> {
  block?: boolean;
  compact?: boolean;
  size?: ButtonBase.ButtonSize;
  subtext?: React.ReactNode;
  badge?: React.ReactNode;
  variant: ButtonBase.ButtonVariant;
  indeterminate?: boolean;
}

export const ToggleButton = React.forwardRef<ToggleButtonDerivedElement, ToggleButtonProps>(({
  children,
  block = false,
  compact = false,
  size = 'medium',
  id: idProp,
  className,
  subtext,
  badge,
  variant,
  indeterminate = false,
  ...etcProps
}, forwardedRef) => {
  const defaultRef = React.useRef<ToggleButtonDerivedElement>(null);
  const ref = forwardedRef ?? defaultRef;
  const defaultId = React.useId();
  const id = idProp ?? defaultId;

  React.useEffect(() => {
    if (!(typeof ref === 'object' && ref)) {
      return;
    }
    const { current: element } = ref;
    if (!element) {
      return;
    }
    element.indeterminate = indeterminate;
  }, [indeterminate, ref]);

  return (
    <>
      <input
        {...etcProps}
        ref={ref}
        type="checkbox"
        id={id}
        className={clsx(
          'sr-only peer',
          styles['toggle-button'],
        )}
      />
      <label
        htmlFor={id}
        className={clsx(
          'items-center justify-start rounded overflow-hidden ring-secondary/50 gap-4 leading-none select-none cursor-pointer',
          'peer-focus:outline-0 peer-focus:ring-4 peer-focus:ring-secondary/50',
          'active:ring-tertiary/50 active:ring-4',
          'peer-disabled:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:ring-0',
          'text-primary peer-disabled:text-primary peer-focus:text-secondary peer-checked:text-tertiary active:text-tertiary',
          {
            'flex w-full': block,
            'inline-flex max-w-full align-middle': !block,
          },
          {
            'pl-2 pr-2': compact,
            'pl-4 pr-4': !compact,
          },
          {
            'border-2 border-primary peer-disabled:border-primary peer-focus:border-secondary peer-checked:border-tertiary active:border-tertiary' : variant !== 'bare',
            'bg-primary text-negative peer-disabled:bg-primary peer-focus:bg-secondary peer-checked:bg-tertiary active:bg-tertiary': variant === 'filled',
          },
          {
            'h-10': size === 'small',
            'h-12': size === 'medium',
            'h-16': size === 'large',
          },
          className,
        )}
      >
        <span
          className={clsx(
            'w-6 h-6 block rounded border-2 p-0.5 box-border',
            {
              'border-current': variant !== 'filled',
              'border-negative': variant === 'filled',
              '-mr-2': compact,
            }
          )}
        >
          <svg
            className={clsx(
              'w-full h-full fill-none stroke-3 linejoin-round linecap-round',
              {
                'stroke-negative': variant === 'filled',
                'stroke-current': variant !== 'filled',
              }
            )}
            viewBox="0 0 24 24"
            role="presentation"
          >
            <polyline
              points="20 6 9 17 4 12"
            />
          </svg>
          <svg
            className={clsx(
              'w-full h-full fill-none stroke-3 linejoin-round linecap-round',
              {
                'stroke-negative': variant === 'filled',
                'stroke-current': variant !== 'filled',
              }
            )}
            viewBox="0 0 24 24"
            role="presentation"
          >
            <polyline
              points="20 12 4 12"
            />
          </svg>
        </span>
        <span
          className={clsx(
            'contents',
            {
              'text-current': variant !== 'filled',
              'text-negative': variant === 'filled',
            },
          )}
        >
          <span
            className={clsx(
              'flex-auto min-w-0',
            )}
          >
            <span
              className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded"
              data-testid="children"
            >
              {children}
            </span>
            {subtext && (
              <>
                <span className="sr-only">
                  {' - '}
                </span>
                <span
                  className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
                  data-testid="subtext"
                >
                  {subtext}
                </span>
              </>
            )}
          </span>
          {badge && (
            <>
              <span className="sr-only">
                {' - '}
              </span>
              <span
                data-testid="badge"
              >
                {badge}
              </span>
            </>
          )}
        </span>
      </label>
    </>
  )
});

ToggleButton.displayName = 'ToggleButton';
