import { CheckIcon, CloseIcon } from '@trail-ui/icons';
import { clsx } from '@trail-ui/shared-utils';
import { FocusEventHandler, ForwardedRef, forwardRef } from 'react';

export interface SwitchProps {
  label?: string;
  labelId?: string;
  ariaLabelledby?: string;
  isToggled: boolean;
  onChange: (value: boolean) => void;
  activeText?: string;
  inactiveText?: string;
  isDisabled?: boolean;
  tabIndex?: number | undefined;
  onFocus?: FocusEventHandler;
  classNames?: {
    base?: string;
    label?: string;
    switch?: string;
    text?: string;
  };
}

const Switch = forwardRef(
  (
    {
      label,
      labelId,
      ariaLabelledby,
      isToggled,
      activeText,
      inactiveText,
      isDisabled = false,
      onChange,
      tabIndex = undefined,
      onFocus,
      classNames,
    }: SwitchProps,
    ref: ForwardedRef<HTMLDivElement>,
  ) => {
    const handleToggle = () => {
      if (isDisabled) {
        return;
      }
      onChange(!isToggled);
    };

    return (
      <div
        className={clsx(
          isDisabled ? 'pointer-events-none select-none opacity-40' : '',
          'flex items-center gap-1.5 text-sm text-neutral-900',
          classNames?.base,
        )}
      >
        {label && (
          <span id={labelId ?? 'label'} className={clsx('mr-0.5', classNames?.label)}>
            {label}
          </span>
        )}
        <div
          role="switch"
          ref={ref}
          aria-labelledby={ariaLabelledby ?? labelId ?? 'label'}
          aria-checked={isToggled}
          tabIndex={tabIndex ?? (isDisabled ? -1 : 0)}
          className={clsx(
            `relative inline-flex h-5 w-10 cursor-pointer items-center rounded-full transition-all duration-300 ease-in-out focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-purple-600`,
            isToggled ? 'bg-purple-600' : 'bg-neutral-600',
            classNames?.switch,
          )}
          onClick={handleToggle}
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') {
              e.preventDefault();
              handleToggle();
            }
          }}
          onFocus={onFocus}
        >
          <div className="absolute inset-0 flex items-center justify-between px-1">
            <CheckIcon className="h-5 w-5 text-neutral-50" />
            <CloseIcon className="h-5 w-5 text-neutral-50" />
          </div>
          <div
            className={`absolute left-0.5 top-0.5 h-4 w-4 rounded-full bg-neutral-50 transition-transform duration-300 ${isToggled ? 'translate-x-5' : 'translate-x-0'}`}
          />
        </div>
        {activeText && (
          <span aria-hidden="true" className={classNames?.text}>
            {isToggled ? activeText : inactiveText}
          </span>
        )}
      </div>
    );
  },
);

Switch.displayName = 'Switch';
export default Switch;
