import { Flex } from 'antd';
import type { InputProps, InputRef } from 'antd';
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { InputUI } from '../../primitives/input';
import { createMultiSegmentValidatorPlugin } from './plugins';
import type { MultiInputParts } from './types';

type MultiInputChangeEvent = Parameters<NonNullable<InputProps['onChange']>>[0];

export type MultiInputUIProps = {
  value?: string;
  defaultValue?: string;
  onChange?: InputProps['onChange'];
  disabled?: boolean;
  size?: InputProps['size'];
  status?: InputProps['status'];
  variant?: InputProps['variant'];
  allowClear?: boolean;
};

function splitValue(value?: string): MultiInputParts {
  const digits = (value ?? '').replace(/\D/g, '').slice(0, 11);
  return [digits.slice(0, 3), digits.slice(3, 7), digits.slice(7, 11)];
}

function createChangeEvent(value: string): MultiInputChangeEvent {
  return {
    target: { value },
    currentTarget: { value },
  } as MultiInputChangeEvent;
}

export const MultiInputUI = forwardRef<InputRef, MultiInputUIProps>(function MultiInputUI(
  { value, defaultValue, onChange, disabled, size, status, variant, allowClear },
  ref,
) {
  const firstRef = useRef<InputRef>(null);
  const secondRef = useRef<InputRef>(null);
  const thirdRef = useRef<InputRef>(null);
  const [parts, setParts] = useState<MultiInputParts>(() => splitValue(value ?? defaultValue));

  useImperativeHandle(ref, () => firstRef.current as InputRef, []);

  useEffect(() => {
    if (value !== undefined) {
      setParts(splitValue(value));
    }
  }, [value]);

  const updatePart = (index: 0 | 1 | 2, nextPart: string) => {
    setParts((previousParts) => {
      const nextParts: MultiInputParts = [...previousParts] as MultiInputParts;
      nextParts[index] = nextPart.replace(/\D/g, '').slice(0, index === 0 ? 3 : 4);
      onChange?.(createChangeEvent(nextParts.join('')));
      return nextParts;
    });
  };

  const commonProps = {
    disabled,
    size,
    status,
    variant,
    allowClear,
    inputMode: 'numeric' as const,
  };

  return (
    <Flex gap="small" align="center">
      <InputUI
        {...commonProps}
        ref={firstRef}
        value={parts[0]}
        maxLength={3}
        placeholder="010"
        commitPlugins={[createMultiSegmentValidatorPlugin(3)]}
        onChange={(event) => {
          updatePart(0, event.target.value);
          if (event.target.value.length === 3) {
            secondRef.current?.focus();
          }
        }}
      />
      <InputUI
        {...commonProps}
        ref={secondRef}
        value={parts[1]}
        maxLength={4}
        placeholder="1234"
        commitPlugins={[createMultiSegmentValidatorPlugin(4)]}
        onChange={(event) => {
          updatePart(1, event.target.value);
          if (event.target.value.length === 4) {
            thirdRef.current?.focus();
          }
        }}
      />
      <InputUI
        {...commonProps}
        ref={thirdRef}
        value={parts[2]}
        maxLength={4}
        placeholder="5678"
        commitPlugins={[createMultiSegmentValidatorPlugin(4)]}
        onChange={(event) => {
          updatePart(2, event.target.value);
        }}
      />
    </Flex>
  );
});
