import type { FC } from 'react';
import React, { useCallback, useState } from 'react';
import {
    Dropdown,
    Field,
    NumberInput,
    Sidecar,
} from '@theorchard/suite-components';
import { formatMessage } from '@theorchard/suite-frontend';
import { IPI_LENGTH, PRO_LIST } from 'src/constants';
import { useUpdatePublisher } from 'src/data/mutations/updatePublisher/updatePublisher';
import { isValidIpi } from 'src/utils/validators';
import type { Publisher } from 'src/types';

const CLASS_NAME = 'EditPublisher';

interface Props {
    isOpen: boolean;
    onClose: (p?: Publisher) => void;
    publisher: Publisher;
}

const EditPublisher: FC<Props> = ({ isOpen, onClose, publisher }) => {
    const [hasSubmitted, setHasSubmitted] = useState(false);
    const [name, setName] = useState<string>(publisher.name || '');
    const [pro, setPro] = useState<string>(publisher.pro || '');
    const [ipi, setIpi] = useState<string>(publisher.ipi || '');
    const [publisherValidationErrorKeys, setPublisherValidationErrorKeys] =
        useState<string[] | null>(null);

    const updatePublisher = useUpdatePublisher(
        (result: object | null, errors?: string[]) => {
            if (result) onClose(result as Publisher);
            else if (errors) setPublisherValidationErrorKeys(errors);
        }
    );

    const nameIsEmpty = !name.length;
    const publisherIpiIsInvalid = ipi && !isValidIpi(ipi);
    const publisherIpiIsNotUnique = publisherValidationErrorKeys?.includes(
        'publisherIPICollision'
    );

    const reset = useCallback(() => {
        setHasSubmitted(false);
        setPublisherValidationErrorKeys(null);
    }, []);

    const closeAndReset = useCallback(() => {
        onClose();
        reset();
    }, [reset, onClose]);

    const onIpiChange = useCallback((value: string) => {
        let formatted = value.slice(-IPI_LENGTH);
        if (value.length < IPI_LENGTH)
            formatted = `00000000000${value}`.slice(-IPI_LENGTH);
        setIpi(formatted);
    }, []);

    const onPublisherUpdate = useCallback(() => {
        setHasSubmitted(true);
        if (
            nameIsEmpty ||
            publisherIpiIsInvalid ||
            publisherValidationErrorKeys
        )
            return;

        void updatePublisher({
            variables: {
                id: publisher.id,
                name,
                ipi,
                pro,
            },
        });
    }, [
        nameIsEmpty,
        publisherIpiIsInvalid,
        publisherValidationErrorKeys,
        publisher,
        name,
        ipi,
        pro,
        updatePublisher,
    ]);

    return (
        <Sidecar
            isOpen={isOpen}
            onRequestClose={closeAndReset}
            className={CLASS_NAME}
            header={formatMessage('publishers.editPublisher')}
            onConfirm={onPublisherUpdate}
        >
            <form>
                <Field
                    controlId="publishingCompany"
                    labelText={formatMessage('generic.publishingCompany')}
                    errorMessage={
                        (hasSubmitted &&
                            nameIsEmpty &&
                            formatMessage('errors.publisherEmptyName')) ||
                        undefined
                    }
                >
                    <input
                        type="text"
                        value={name}
                        onChange={e => setName(e.target.value)}
                        placeholder={formatMessage(
                            'songWriterManager.publisherNamePlaceholder'
                        )}
                        className="form-control"
                    />
                </Field>
                <Field
                    controlId="publishingCompanyPro"
                    labelText={formatMessage('generic.publishingCompanyPro')}
                >
                    <Dropdown
                        options={PRO_LIST.map((p: string) => ({
                            value: p,
                            label: p,
                        }))}
                        placeholder={formatMessage(
                            'songWriterManager.publisherProPlaceholder'
                        )}
                        selectedValue={pro}
                        onChange={option => setPro(option?.value || '')}
                    />
                </Field>
                <Field
                    controlId="publishingCompanyIpi"
                    labelText={formatMessage('generic.publishingCompanyIpi')}
                    errorMessage={
                        (hasSubmitted &&
                            ((publisherIpiIsInvalid &&
                                formatMessage('errors.ipiNeeds9Chars')) ||
                                (publisherIpiIsNotUnique &&
                                    formatMessage(
                                        'errors.publisherIPICollision'
                                    )))) ||
                        undefined
                    }
                >
                    <NumberInput
                        value={ipi}
                        onChange={onIpiChange}
                        allowNegatives={false}
                        placeholder={formatMessage(
                            'songWriterManager.publisherIpiPlaceholder'
                        )}
                    />
                </Field>
            </form>
        </Sidecar>
    );
};

export default EditPublisher;
