import styled from '@emotion/styled';
import { useCallback, useEffect, useState } from 'react';

import { MinusIcon, PlusIcon } from '@/icons';

import Button, { ButtonShape } from '../button/Button';

const Wrapper = styled.div`
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 10px;
`;

const Input = styled.input`
  flex-grow: 1;
  text-align: center;
  border-radius: 4px;
  background-color: var(--color-background-tertiary);
  height: 32px;
  font-size: 18px;
  min-width: 140px;
  width: 0;
  &:focus {
    outline: 1px solid var(--color-border-secondary);
  }
  &:disabled {
    opacity: 0.5;
  }
`;

export default function PlusMinusInput({
  autoFocus,
  value,
  onChange,
  disabled,
  plusTransform,
  minusTransform,
  min = -Infinity,
  max = Infinity,
}: {
  autoFocus: boolean;
  value: number;
  onChange: (value: number) => void;
  disabled: boolean;
  plusTransform: (prev: number) => number;
  minusTransform: (prev: number) => number;
  min?: number;
  max?: number;
}) {
  const [localValue, setLocalValue] = useState(String(value));
  useEffect(() => {
    setLocalValue(value.toFixed(2));
  }, [value]);
  const isValid = useCallback(
    (value: string) => {
      const num = Number(value);
      return !isNaN(num) && num >= min && num <= max;
    },
    [min, max]
  );
  const handlePlus = useCallback(() => {
    const newValue = plusTransform(Number(localValue));
    if (isValid(String(newValue))) {
      setLocalValue(newValue.toFixed(2));
      onChange(newValue);
    }
  }, [plusTransform, localValue, isValid, onChange]);

  const handleMinus = useCallback(() => {
    const newValue = minusTransform(Number(localValue));
    if (isValid(String(newValue))) {
      setLocalValue(newValue.toFixed(2));
      onChange(newValue);
    }
  }, [minusTransform, localValue, isValid, onChange]);
  return (
    <Wrapper>
      <Button
        disabled={disabled}
        shape={ButtonShape.Pill}
        icon={MinusIcon}
        onClick={handleMinus}
      />
      <Input
        onFocus={(e) => {
          setTimeout(() => e.target.select());
        }}
        autoFocus={autoFocus}
        disabled={disabled}
        value={localValue}
        onChange={(e) => setLocalValue(e.target.value)}
        onKeyDown={(e) => {
          if (e.key === 'Enter') {
            if (isValid(localValue)) {
              onChange(Number(localValue));
            } else {
              e.stopPropagation();
              e.preventDefault();
            }
          } else if (e.key === 'ArrowUp') {
            handlePlus();
          } else if (e.key === 'ArrowDown') {
            handleMinus();
          } else if (e.key === 'Escape') {
            setLocalValue(value.toFixed(2));
          }
        }}
        onBlur={() => {
          if (isValid(localValue)) {
            onChange(Number(localValue));
          } else {
            setLocalValue(value.toFixed(2));
          }
        }}
      />
      <Button
        disabled={disabled}
        shape={ButtonShape.Pill}
        icon={PlusIcon}
        onClick={handlePlus}
      />
    </Wrapper>
  );
}
