import React, { useEffect, useState } from 'react';
import { Alert, Modal, Form, Field } from '@theorchard/suite-components';
import { isEmpty, trim } from 'lodash-es';
import { useCreateRunController } from 'src/apollo/mutations/run-controller';
import ContractTypeSelect from 'src/components/shared/contract-type-select';
import { CONTRACT_TYPES } from 'src/constants';
import { CONTRACT_TYPE_MAP } from 'src/apollo/type-constants/contract';
import { runControllerFormValidation } from 'src/utils/form-validations/run-controller-form-validation';
import type {
    RunControllerFormErrors,
    RunControllerFormFields,
} from 'src/types/run-controller';

export interface RunControllerFormModalPropsTypes {
    isRunControllerFormModalOpen: boolean;
    onRequestCloseModal: () => void;
}

export const RunControllerFormModal: React.FC<
    RunControllerFormModalPropsTypes
> = ({ isRunControllerFormModalOpen, onRequestCloseModal }) => {
    const [formErrors, setFormErrors] = useState<
        Partial<RunControllerFormErrors> | undefined
    >(undefined);
    const [serverError, setServerError] = useState<string>('');
    const [isSaveDisabled, setIsSaveDisabled] = useState<boolean>(false);
    const [formData, setFormData] = useState<RunControllerFormFields>({
        contractType: CONTRACT_TYPES.DISTRIBUTION,
        runControllerName: '',
    });

    const addRunController = useCreateRunController();

    useEffect(() => {
        setFormData({
            contractType: CONTRACT_TYPES.DISTRIBUTION,
            runControllerName: '',
        });
        setIsSaveDisabled(false);
        setFormErrors({});
        setServerError('');
    }, [isRunControllerFormModalOpen]);

    const changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
        const {
            target: { name, value },
        } = e;

        setFormErrors({});
        setServerError('');
        setFormData({
            ...formData,
            [name]: value,
        });
    };

    const saveNewRunController = () => {
        setIsSaveDisabled(true);
        const validationErrors = runControllerFormValidation(formData);

        if (!isEmpty(validationErrors)) {
            setFormErrors(validationErrors);
            setIsSaveDisabled(false);
            return;
        }

        const { runControllerName, contractType } = formData;
        const variables = {
            runControllerName: trim(runControllerName),
            contractType,
        };
        return addRunController({ variables })
            .then(() => {
                setIsSaveDisabled(false);
                onRequestCloseModal();
            })
            .catch(e => {
                setIsSaveDisabled(false);
                if (e instanceof Error) {
                    setServerError(
                        `Error: ${e.message}, Failed to create run controller.`
                    );

                    if (Array.isArray(e))
                        setServerError(
                            `Error: ${JSON.stringify(e[0])}, Failed to create run controller.`
                        );
                    else
                        setServerError(
                            `Error: ${String(e)}, Failed to create run controller.`
                        );
                }
            });
    };

    const modalContent = (
        <div className="RunControllerForm">
            {serverError && (
                <Alert
                    className="RunControllerForm-Error"
                    variant="error"
                    text={<span>{serverError}</span>}
                />
            )}
            <Form.Group className="RunControllerFormFields">
                <Field
                    controlId="ContractTypeSelect"
                    labelText="Contract Type"
                    errorMessage={
                        (formErrors as RunControllerFormErrors)?.contractType ||
                        undefined
                    }
                    isRequired={true}
                >
                    <ContractTypeSelect
                        className="ContractTypeSelect"
                        id="ContractTypeSelect"
                        isClearable={false}
                        name="contractType"
                        onChange={(
                            e: Record<string, keyof typeof CONTRACT_TYPE_MAP>
                        ) =>
                            changeHandler({
                                target: {
                                    name: 'contractType',
                                    value: e.value,
                                },
                            } as any)
                        }
                        value={formData.contractType}
                    />
                </Field>
                <Field
                    controlId="RunControllerName"
                    labelText="Name"
                    errorMessage={
                        (formErrors as RunControllerFormErrors)
                            ?.runControllerName || undefined
                    }
                    isRequired={true}
                >
                    <input
                        className="form-control"
                        data-testid="run-controller-name"
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
                            changeHandler(e)
                        }
                        name="runControllerName"
                        placeholder="Type a name..."
                        type="text"
                        value={formData.runControllerName}
                    />
                </Field>
            </Form.Group>
        </div>
    );

    return (
        <Modal
            className="RunControllerForm"
            confirmDisabled={isSaveDisabled}
            confirmTitle="Create"
            isOpen={isRunControllerFormModalOpen}
            onConfirm={saveNewRunController}
            onRequestClose={
                isSaveDisabled
                    ? () => false
                    : () => {
                          setIsSaveDisabled(false);
                          onRequestCloseModal();
                      }
            }
            testId="RunControllerForm"
            title="New Run Controller"
        >
            {modalContent}
        </Modal>
    );
};
