import { useCallback, useEffect, useState } from 'react';

import type { WithSpacingProps } from '~/src/lib/hocs/withSpacing';

import withSpacing from '~/src/lib/hocs/withSpacing';
import Clickable from '../Clickable';
import HoverBackground from '../HoverBackground';
import TickIcon from '../Icon/TickIcon';

export interface SwitchProps extends WithSpacingProps {
  size?: number | string;
  value?: boolean;
  defaultValue?: boolean;
  onChange?: (value: boolean, updateValue: (value: boolean) => void) => void;
  color?: string;
  testId?: string;
  name?: string;
  isDisabled?: boolean;
}

const Switch = withSpacing<SwitchProps>((props) => {
  const {
    style,
    className,
    value,
    defaultValue,
    size = '2.7rem',
    onChange,
    testId,
    color,
    name,
    isDisabled,
  } = props;

  const initialValue = 'defaultValue' in props ? defaultValue : value;
  const [internalValue, setInternalValue] = useState(initialValue);

  // handle 'controlled' use-case
  useEffect(() => {
    if (value !== undefined) {
      setInternalValue(value);
    }
  }, [value]);

  return (
    <Clickable
      testId={testId}
      onClick={useCallback(() => {
        const newValue = !internalValue;

        setInternalValue(newValue);
        onChange?.(newValue, setInternalValue);
      }, [internalValue, onChange])}
      withActiveStyle={false}
      className={className}
      isDisabled={isDisabled}
      style={{
        ...style,
        fontSize: size,
        height: '1em',
        width: '1.5em',
        background: '#393939',
        position: 'relative',
        borderRadius: '0.5em',
      }}
    >
      <div
        style={{
          opacity: internalValue ? 0.85 : 0,
          backgroundColor: color || '#fff',
          transition: 'opacity 200ms',
          width: '100%',
          height: '100%',
          borderRadius: '0.5em',
        }}
      />
      <div
        style={{
          borderRadius: '0.5em',
          width: '1em',
          height: '1em',
          transform: `translateX(${internalValue ? '0.5' : '0'}em)`,
          transition: 'transform 200ms',
          position: 'absolute',
          left: 0,
          top: 0,
          padding: '0.08em',
        }}
      >
        <HoverBackground>
          <div
            style={{
              borderRadius: '0.5em',
              background: '#000',
              width: '100%',
              height: '100%',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            <TickIcon
              size=".55em"
              margin=".02em 0 0"
              style={{
                color: '#fff',
                transition: 'opacity 200ms, transform 200ms',
                opacity: internalValue ? 0.8 : 0,
                transform: internalValue ? 'scale(1)' : 'scale(0.8)',
                transitionDelay: internalValue ? '120ms' : '0ms',
              }}
            />
          </div>
        </HoverBackground>
      </div>
      <input
        type="checkbox"
        hidden
        readOnly
        checked={internalValue}
        name={name}
      />
    </Clickable>
  );
});

export default Switch;
