import { FunctionComponent, useState, useEffect, useContext } from 'react';
import { useRouter } from 'next/router';
import { NotAllowedIcon, CheckIcon } from "@chakra-ui/icons";
import { InputGroup, InputLeftAddon, Spinner, Box, Input, InputRightElement } from '@chakra-ui/react';
import useDebounce from '../../../utils/hooks/useDebounce';
import { AdditionalValidation } from './AdditionalValidationContext';
import { isCoindropUrlAvailable } from '../../../src/db/queries/coindrops/isCoindropUrlAvailable';
import { piggybankPathRegex } from '../../../src/settings';
import { CoindropRequirements } from '../../CoindropRequirements/CoindropRequirements';
import { CreateCoindropError } from '../../CreatePiggybankInput/CreateCoindropError';

type StatusIconProps = {
    value: string
    debouncedValue: string
    isValidating: boolean
    isValid: boolean
    currentPiggybankId: string
};
const StatusIcon: FunctionComponent<StatusIconProps> = ({
    value,
    debouncedValue,
    isValidating,
    isValid,
    currentPiggybankId,
}) => {
    if (isValidating || value !== debouncedValue) {
        return (
            <Box>
                <Spinner size="sm" />
            </Box>
        );
    }
    if (isValid || value === currentPiggybankId) {
        return (
            <CheckIcon id="piggybank-id-ok" color="green.500" />
        );
    }
    return <NotAllowedIcon id="piggybank-id-not-allowed" color="red.500" />;
};

type Props = {
    register: any // from react-hook-form useForm
    value: string
}

const EditUrlInput: FunctionComponent<Props> = ({ register, value }) => {
    const { query: { piggybankName }} = useRouter();
    const currentPiggybankId = Array.isArray(piggybankName) ? piggybankName[0] : piggybankName;
    const [isValidating, setIsValidating] = useState(false);
    const [isValid, setIsValid] = useState(false);
    const [error, setError] = useState<'Invalid input' | 'Id taken' | 'Network error'>();
    const debouncedValue = useDebounce(value, 1500);
    const { setIsPiggybankIdAvailable } = useContext(AdditionalValidation);
    const isUrlUnchanged = value === currentPiggybankId;
    const isInvalid = !debouncedValue.match(piggybankPathRegex);
    const validateIsAvailable = async () => {
        if (isUrlUnchanged) {
            setIsValid(true);
            setIsPiggybankIdAvailable(true);
            setError(null);
            setIsValidating(false);
            return;
        }
        if (isInvalid) {
            setIsValid(false);
            setIsPiggybankIdAvailable(false);
            setError('Invalid input');
            setIsValidating(false);
            return;
        }
        try {
            const isAvailable = await isCoindropUrlAvailable(debouncedValue);
            setIsValid(isAvailable && !isInvalid);
            setIsPiggybankIdAvailable(isAvailable && !isInvalid);
            if (!isAvailable) {
                setError('Id taken');
            }
        } catch (err) {
            setIsValid(false);
            setIsPiggybankIdAvailable(false);
            setError('Network error');
        } finally {
            setIsValidating(false);
        }
    };
    useEffect(() => {
        validateIsAvailable();
    }, [debouncedValue]);
    useEffect(() => {
        setIsValidating(true);
        setError(null);
    }, [value]);
    useEffect(() => {
        setIsValidating(false);
    }, []);
    return (
        <>
        <InputGroup>
            <InputLeftAddon>
                coindrop.to/
            </InputLeftAddon>
            <Input
                id="input-piggybankId"
                maxLength={32}
                roundedLeft="0"
                isInvalid={!isValid && !isValidating && value === debouncedValue && !isUrlUnchanged}
                ref={register}
                name="piggybankId"
            />
            <InputRightElement>
                <StatusIcon
                    value={value}
                    debouncedValue={debouncedValue}
                    currentPiggybankId={currentPiggybankId}
                    isValid={isValid}
                    isValidating={isValidating}
                />
            </InputRightElement>
        </InputGroup>
        {error === 'Invalid input' && (
            <CoindropRequirements />
        )}
        {error === 'Id taken' && (
            <CreateCoindropError
                error="URL is taken, try another!"
            />
        )}
        {error === 'Network error' && (
            <CreateCoindropError
                error="Error checking availability, please try again"
            />
        )}
        </>
    );
};

export default EditUrlInput;