import React, { memo, useEffect, useRef, useState } from "react";
import { isNumber } from "@ax/helpers";
import { validateTimeAndCursor } from "./utils";

import * as S from "./style";

const HourInput = (props: IProps) => {
	const { value, onChange, disabled } = props;

	const [cursorPosition, setCursorPosition] = useState(0);
	const [count, setCount] = useState(0);
	const inputRef = useRef<HTMLInputElement>(null);

	useEffect(() => {
		inputRef.current?.setSelectionRange(cursorPosition, cursorPosition);
	}, [count, cursorPosition]);

	const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
		const oldValue = value;
		const inputEl = e.target;
		const inputValue = inputEl.value;
		const position = inputEl.selectionEnd || 0;
		const isTyped = inputValue.length > oldValue.length;
		const cursorCharacter = inputValue[position - 1];
		const addedCharacter = isTyped ? cursorCharacter : null;
		const removedCharacter = isTyped ? null : oldValue[position];
		const replacedSingleCharacter = inputValue.length === oldValue.length ? oldValue[position - 1] : null;
		const colon = ":";

		let newValue = oldValue;
		let newPosition = position;

		if (addedCharacter !== null) {
			if (position > 5) {
				newPosition = 5;
			} else if (position === 3 && addedCharacter === colon) {
				newValue = `${inputValue.slice(0, position - 1)}${colon}${inputValue.slice(position + 1)}`;
			} else if (position === 3 && isNumber(addedCharacter)) {
				newValue = `${inputValue.slice(0, position - 1)}${colon}${addedCharacter}${inputValue.slice(position + 2)}`;
				newPosition = position + 1;
			} else if (isNumber(addedCharacter)) {
				// user typed a number
				newValue = inputValue.slice(0, position - 1) + addedCharacter + inputValue.slice(position + 1);
				if (position === 2) {
					newPosition = position + 1;
				}
			} else {
				// if user typed NOT a number, then keep old value & position
				newPosition = position - 1;
			}
		} else if (replacedSingleCharacter !== null) {
			// user replaced only a single character
			if (isNumber(cursorCharacter)) {
				if (position - 1 === 2) {
					newValue = `${inputValue.slice(0, position - 1)}${colon}${inputValue.slice(position)}`;
				} else {
					newValue = inputValue;
				}
			} else {
				// user replaced a number on some non-number character
				newValue = oldValue;
				newPosition = position - 1;
			}
		} else if (typeof cursorCharacter !== "undefined" && cursorCharacter !== colon && !isNumber(cursorCharacter)) {
			// set of characters replaced by non-number
			newValue = oldValue;
			newPosition = position - 1;
		} else if (removedCharacter !== null) {
			if (position === 2 && removedCharacter === colon) {
				newValue = `${inputValue.slice(0, position - 1)}0${colon}${inputValue.slice(position)}`;
				newPosition = position - 1;
			} else {
				// user removed a number
				newValue = `${inputValue.slice(0, position)}0${inputValue.slice(position)}`;
			}
		}

		const [validatedTime, validatedCursorPosition] = validateTimeAndCursor(newValue, oldValue, newPosition);

		setCursorPosition(validatedCursorPosition);
		setCount(count + 1);
		onChange(validatedTime);
	};

	return (
		<S.InputField
			type="text"
			value={value}
			onChange={handleChange}
			ref={inputRef}
			disabled={disabled}
			data-testid="time-field-input"
		/>
	);
};

interface IProps {
	value: string;
	onChange: (value: string) => void;
	disabled?: boolean;
}

export default memo(HourInput);
