import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react';
import { __ } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom';
import { is, isEmpty, isNil, pathOr } from 'ramda';
import { wrap } from 'object-path-immutable';
import { klona } from 'klona';
import { useForm } from 'react-hook-form';

// store
import { storeSet, useStoreValue } from '../../store';

// api
import AmendmentsService from '../../service/amendments-service';

// tools
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import getBandoLabel from '../../helpers/getBandoLabel';
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
import getEmailTemplateForSoccorso from '../../helpers/getStrippedHtmlBodyTags';

// components
import { Button } from 'primereact/button';
import BlockingOverlay from '../../components/BlockingOverlay';
import { Toast } from 'primereact/toast';
import { classNames } from 'primereact/utils';
import { Dialog } from 'primereact/dialog';
import FormField from '../../components/FormField';
import { Editor } from 'primereact/editor';
import { InputNumber } from 'primereact/inputnumber';
import SoccorsoComunications from '../SoccorsoEditPreInstructor/components/SoccorsoComunications';
import SoccorsoResendEmails from '../SoccorsoEditPreInstructor/components/SoccorsoResendEmails';

import { amendmentRequestedDocs } from '../../configData';

const SoccorsoEditInstructorManager = () => {
    const isAsyncRequest = useStoreValue('isAsyncRequest');
    const { id, amendmentId } = useParams();
    const navigate = useNavigate();
    const [data, setData] = useState({});
    const [isVisibleCloseAmendDialog, setIsVisibleCloseAmendDialog] = useState(false);
    const [isVisibleExtendTimeDialog, setIsVisibleExtendTimeDialog] = useState(false);
    const [extendedTime, setExtendedTime] = useState(3);
    const [isLoadingExtendingTime, setIsLoadingExtendingTime] = useState(false);
    const [isLoadingReminding, setIsLoadingReminding] = useState(false);
    const [internalNote, setInternalNote] = useState('');
    const toast = useRef(null);
    const [formInitialData, setFormInitialData] = useState({});
    const emailSendResponse = pathOr([], ['emailSendResponse'], data);
    const {
        control,
        handleSubmit,
        formState: { errors },
        setValue,
        register,
        trigger,
        getValues
    } = useForm({
        defaultValues: useMemo(() => {
            return formInitialData;
        }, [formInitialData]), mode: 'onChange'
    });

    const goToEvaluationPage = () => {
        navigate(`/mie-domande/${id}`);
    }

    const getCallback = (data) => {
        if (data.status === 'SUCCESS') {
            setData(getFormattedData(data.data));
            let formDataInitial = data.data.applicationFormFields.reduce((acc, cur) => {
                if (cur.fieldValue) {
                    acc[cur.fieldId] = cur.fieldValue;
                }
                return acc;
            }, {});
            formDataInitial = {
                ...formDataInitial,
                amendmentDocuments: data.data.amendmentDocuments
            }
            setFormInitialData(formDataInitial);
        }
        storeSet('unsetAsyncRequest');
    }

    const errGetCallback = (data) => {
        if (toast.current && data.message) {
            toast.current.show({
                severity: 'error',
                summary: '',
                detail: data.message
            });
        }
        set404FromErrorResponse(data);
        storeSet('unsetAsyncRequest');
    }

    const getFormattedData = (data) => {
        data.startDate = is(String, data.startDate) ? new Date(data.startDate) : (data.startDate ? data.startDate : '');
        data.expirationDate = is(String, data.expirationDate) ? new Date(data.expirationDate) : (data.expirationDate ? data.expirationDate : '');
        return data;
    };

    const renderHeader = () => {
        return (
            <span className="ql-formats">
                <button className="ql-bold" aria-label="Bold"></button>
                <button className="ql-italic" aria-label="Italic"></button>
                <button className="ql-underline" aria-label="Underline"></button>
                <button className="ql-link" aria-label="Link"></button>
                <button className="ql-list" value="ordered"></button>
                <button className="ql-header" value="2"></button>
                <button className="ql-header" value="3"></button>
                <button className="ql-blockquote"></button>
                <button className="ql-list" value="bullet"></button>
                <button className="ql-indent" value="-1"></button>
                <button className="ql-indent" value="+1"></button>
            </span>
        );
    };

    const header = renderHeader();

    const updateNewAmendmentData = (value, path) => {
        const newData = wrap(data).set(path, value).value();
        setData(newData);
    }

    const onSubmit = () => {
    };

    const doUpdateAmendment = (doClose = false) => {
        trigger();
        let formValues = klona(getValues());
        const newFormValues = Object.keys(formValues)
            .filter(v => v !== 'amendmentDocuments')
            .reduce((acc, cur) => {
                let fieldVal = formValues[cur];

                fieldVal = isEmpty(fieldVal) ? null : fieldVal;
                fieldVal = is(Array, fieldVal) ? fieldVal.map(o => o.id).join(',') : null;

                acc.push({
                    'fieldId': cur,
                    'fieldValue': fieldVal
                });
                return acc;
            }, []);
        const newAmendDocs = formValues.amendmentDocuments
            ? formValues.amendmentDocuments.map(o => o.id).join(',')
            : '';

        const submitData = {
            applicationFormFields: newFormValues,
            amendmentDocuments: newAmendDocs,
            amendmentNotes: data.amendmentNotes
        }

        storeSet('setAsyncRequest');
        AmendmentsService.updateSoccorso(
            amendmentId,
            submitData,
            (resp) => updateAmendmentCallback(resp, doClose),
            errUpdateAmendmentCallback
        );
    }

    const updateAmendmentCallback = (data, doClose = false) => {
        if (data.status === 'SUCCESS') {
            setData(getFormattedData(data.data));

            if (doClose) {
                const submitData = {
                    internalNote
                }
                storeSet('setAsyncRequest');
                AmendmentsService.closeSoccorso(amendmentId, submitData, closeAmendmentCallback, errCloseAmendmentCallback);
            } else {
                if (toast.current) {
                    toast.current.show({
                        severity: 'success',
                        summary: '',
                        detail: data.message
                    });
                }
                let formDataInitial = data.data.applicationFormFields.reduce((acc, cur) => {
                    if (cur.fieldValue) {
                        acc[cur.fieldId] = cur.fieldValue;
                    }
                    return acc;
                }, formInitialData);
                formDataInitial = {
                    ...formDataInitial,
                    amendmentDocuments: data.data.amendmentDocuments
                }
                setFormInitialData(formDataInitial);
            }
        }
        storeSet('unsetAsyncRequest');
    }

    const errUpdateAmendmentCallback = (data) => {
        if (toast.current && data.message) {
            toast.current.show({
                severity: 'error',
                summary: '',
                detail: data.message
            });
        }
        set404FromErrorResponse(data);
        storeSet('unsetAsyncRequest');
    }

    const openCloseAmendmentDialog = () => {
        setIsVisibleCloseAmendDialog(true);
    }

    const headerCloseAmendDialog = () => {
        return <span>{__('Chiudi Soccorso Istruttorio', 'gepafin')}</span>
    }

    const hideCloseAmendDialog = () => {
        setIsVisibleCloseAmendDialog(false);
    }

    const footerCloseAmendDialog = () => {
        return <div>
            <Button type="button" label={__('Annulla', 'gepafin')} onClick={hideCloseAmendDialog} outlined/>
            <Button
                type="button"
                disabled={isAsyncRequest || isEmpty(data.internalNotes)}
                label={__('Invia', 'gepafin')} onClick={doCloseAmendment}/>
        </div>
    }

    const doCloseAmendment = useCallback(() => {
        if (data.status === 'AWAITING') {
            const submitData = {
                internalNote
            }
            storeSet('setAsyncRequest');
            AmendmentsService.closeSoccorso(amendmentId, submitData, closeAmendmentCallback, errCloseAmendmentCallback);
        } else {
            doUpdateAmendment(true);
        }
    }, [data]);

    const closeAmendmentCallback = (data) => {
        if (data.status === 'SUCCESS') {
            if (toast.current) {
                toast.current.show({
                    severity: 'success',
                    summary: '',
                    detail: data.message
                });
            }
            if (data.data.status) {
                updateNewAmendmentData(data.data.status, ['status']);
                setIsVisibleCloseAmendDialog(false);
            }
        }
        storeSet('unsetAsyncRequest');
    }

    const errCloseAmendmentCallback = (data) => {
        if (toast.current && data.message) {
            toast.current.show({
                severity: 'error',
                summary: '',
                detail: data.message
            });
        }
        set404FromErrorResponse(data);
        storeSet('unsetAsyncRequest');
    }

    const headerExtendRespDialog = () => {
        return <span>{__('Estendi scadenza', 'gepafin')}</span>
    }

    const hideExtendRespDialog = () => {
        setIsVisibleExtendTimeDialog(false);
    }

    const footerExtendRespDialog = () => {
        return <div>
            <Button type="button" label={__('Annulla', 'gepafin')} onClick={hideExtendRespDialog} outlined/>
            <Button
                type="button"
                disabled={isLoadingExtendingTime || isEmpty(extendedTime)}
                label={__('Invia', 'gepafin')} onClick={doExtendTimeResponse}/>
        </div>
    }

    const openExtendResponseTimeDialog = () => {
        setIsVisibleExtendTimeDialog(true);
        setExtendedTime(3);
    }

    const doExtendTimeResponse = () => {
        setIsLoadingExtendingTime(true);
        AmendmentsService.extendSoccorso(amendmentId, extendedTime, extendCallback, errExtendCallback);
    }

    const extendCallback = (data) => {
        if (data.status === 'SUCCESS') {
            if (toast.current) {
                toast.current.show({
                    severity: 'success',
                    summary: '',
                    detail: data.message
                });
            }
            setIsVisibleExtendTimeDialog(false);
        }
        setIsLoadingExtendingTime(false);
    }

    const errExtendCallback = (data) => {
        if (toast.current && data.message) {
            toast.current.show({
                severity: 'error',
                summary: '',
                detail: data.message
            });
        }
        set404FromErrorResponse(data);
        setIsLoadingExtendingTime(false);
    }

    const sendReminder = () => {
        setIsLoadingReminding(true);
        AmendmentsService.sendReminderForSoccorso(amendmentId, reminderCallback, errReminderCallback)
    }

    const reminderCallback = (data) => {
        if (data.status === 'SUCCESS') {
            if (toast.current) {
                toast.current.show({
                    severity: 'success',
                    summary: '',
                    detail: data.message
                });
            }
        }
        setIsLoadingReminding(false);
    }

    const errReminderCallback = (data) => {
        if (toast.current && data.message) {
            toast.current.show({
                severity: 'error',
                summary: '',
                detail: data.message
            });
        }
        set404FromErrorResponse(data);
        setIsLoadingReminding(false);
    }

    const updateEmailSendResponses = useCallback((newEmailData) => {
        const newData = wrap(data).set(['emailSendResponse'], newEmailData).value();
        setData(newData);
    }, [data]);

    useEffect(() => {
        if (formInitialData) {
            Object.keys(formInitialData).map(k => setValue(k, formInitialData[k]));
            trigger();
        }
    }, [formInitialData]);

    useEffect(() => {
        const parsedSoccorsoId = parseInt(amendmentId);
        const soccorsoEntityId = !isNaN(parsedSoccorsoId) ? parsedSoccorsoId : 0;

        AmendmentsService.getSoccorsoById(getCallback, errGetCallback, [['id', soccorsoEntityId]]);
    }, [amendmentId]);

    return (
        <div className="appPage">
            <div className="appPage__pageHeader">
                <h1>{__('Soccorso Istruttorio - Dettagli', 'gepafin')}</h1>
            </div>

            <div className="appPage__spacer"></div>
            <Toast ref={toast}/>
            <BlockingOverlay shouldDisplay={isAsyncRequest}/>

            <div className="appPageSection__row">
                <Button
                    type="button"
                    outlined
                    onClick={goToEvaluationPage}
                    label={__('Indietro', 'gepafin')}
                    icon="pi pi-arrow-left" iconPos="left"/>
            </div>

            <div className="appPage__spacer"></div>

            <div className="appPage__content">
                <div className="appPageSection__withBorder columns">
                    <p className="appPageSection__pMeta">
                        <span>{__('ID domanda', 'gepafin')}</span>
                        <span>{data.applicationId}</span>
                    </p>
                    <p className="appPageSection__pMeta">
                        <span>{__('Bando', 'gepafin')}</span>
                        <span>{data.callName}</span>
                    </p>
                    <p className="appPageSection__pMeta">
                        <span>{__('Referente Aziendale', 'gepafin')}</span>
                        <span>{data.beneficiaryName}</span>
                    </p>
                    <p className="appPageSection__pMeta">
                        <span>{__('Inizio', 'gepafin')}</span>
                        <span>{getDateFromISOstring(data.startDate)}</span>
                    </p>
                    <p className="appPageSection__pMeta">
                        <span>{__('Scadenza', 'gepafin')}</span>
                        <span>{getDateFromISOstring(data.expirationDate)}</span>
                    </p>
                    <p className="appPageSection__pMeta">
                        <span>{__('Stato', 'gepafin')}</span>
                        <span>{getBandoLabel(data.status)}</span>
                    </p>
                </div>

                <div className="appPageSection">
                    <h2>{__('Dettagli richiesta', 'gepafin')}</h2>
                    <h3>{__('Note e spiegazioni', 'gepafin')}</h3>
                    <div
                        className="appPageSection__emailTemplate">{getEmailTemplateForSoccorso(data.emailTemplate, data.note)}</div>
                </div>

                {data.amendmentInitialDocument && is(Array, data.amendmentInitialDocument)
                    ? <div className="appPageSection">
                        <h3>{__('Documenti da PEC', 'gepafin')}</h3>
                        <ol className="appPageSection__list">
                            {data.amendmentInitialDocument.map((o, i) => <li key={o.fieldId}>
                                <a href={o.filePath} target="_blank" rel="noreferrer">{o.name}</a>
                            </li>)}
                        </ol>
                    </div> : null}

                {(data.formFields && !isEmpty(data.formFields)) || (data.amendmentType === 'SPECIAL' && !isNil(data.amendmentDocumentType)
                && !isNil(amendmentRequestedDocs[data.amendmentDocumentType])  && !isNil(amendmentRequestedDocs[data.amendmentDocumentType].map))
                    ? <div className="appPageSection">
                        <h3>{__('Documenti richiesti', 'gepafin')}</h3>
                        <ol className="appPageSection__list">
                            {data.formFields && !isEmpty(data.formFields)
                                ? data.formFields.map((o, i) => <li key={o.fieldId}
                                                               style={{ flexDirection: 'row' }}>
                                <span>{o.label}</span>
                            </li>) : null}
                            {!isNil(amendmentRequestedDocs[data.amendmentDocumentType]) ?? !isNil(amendmentRequestedDocs[data.amendmentDocumentType].map)
                                ? amendmentRequestedDocs[data.amendmentDocumentType].map((v) => <li key={v}
                                                                                       style={{ flexDirection: 'row' }}>
                                <span>{v}</span>
                            </li>) : null}
                        </ol>
                    </div> : null}

                <div className="appPageSection">
                    <h2>{__('Comunicazioni', 'gepafin')}</h2>
                    <SoccorsoComunications amendmentId={amendmentId} soccorsoStatus={data.status}/>
                </div>

                {data.formFields && !isEmpty(data.formFields)
                    ? <div className="appPageSection">
                        <h2>{__('Documenti Ricevuti', 'gepafin')}</h2>

                        <form className="appForm" onSubmit={handleSubmit(onSubmit)}>
                            {data.formFields.map((o, i) => {
                                return <FormField
                                    key={o.fieldId}
                                    disabled={['CLOSE', 'AWAITING', 'EXPIRED'].includes(data.status)}
                                    type="fileupload"
                                    setDataFn={setValue}
                                    saveFormCallback={doUpdateAmendment}
                                    fieldName={o.fieldId}
                                    label={o.label}
                                    control={control}
                                    register={register}
                                    errors={errors}
                                    defaultValue={formInitialData[o.fieldId] ? formInitialData[o.fieldId] : []}
                                    accept={[]}
                                    source="AMENDMENT"
                                    sourceId={amendmentId}
                                    multiple={true}
                                />
                            })}
                        </form>
                    </div> : null}

                <div className="appPageSection">
                    <h2>{__('Documenti aggiuntivi', 'gepafin')}</h2>
                    <div className="appPageSection">
                        <h3>{__('Notes', 'gepafin')}</h3>
                        <div style={{ marginBottom: '30px', width: '100%', position: 'relative' }} translate="no">
                            <BlockingOverlay shouldDisplay={['CLOSE', 'AWAITING', 'EXPIRED'].includes(data.status)}/>
                            <Editor
                                value={data.amendmentNotes}
                                readOnly={['CLOSE', 'AWAITING', 'EXPIRED'].includes(data.status)}
                                placeholder={__('Digita qui il messagio', 'gepafin')}
                                headerTemplate={header}
                                onTextChange={(e) => updateNewAmendmentData(
                                    e.htmlValue,
                                    'amendmentNotes'
                                )}
                                style={{ height: 80 * 3, width: '100%' }}
                            />
                        </div>
                        <FormField
                            type="fileupload"
                            disabled={['CLOSE', 'AWAITING', 'EXPIRED'].includes(data.status)}
                            setDataFn={setValue}
                            saveFormCallback={doUpdateAmendment}
                            fieldName="amendmentDocuments"
                            label={__('I file', 'gepafin')}
                            control={control}
                            register={register}
                            errors={errors}
                            defaultValue={formInitialData.amendmentDocuments ? formInitialData.amendmentDocuments : []}
                            accept={[]}
                            source="amendment"
                            sourceId={amendmentId}
                            multiple={true}
                        />
                    </div>
                </div>

                <div className="appPage__spacer"></div>

                <div className="appPageSection__hr">
                    <span>{__('Azioni', 'gepafin')}</span>
                </div>

                <div className="appPageSection">
                    <div className="appPageSection__actions">
                        <Button
                            type="button"
                            onClick={sendReminder}
                            disabled={isLoadingReminding || ['CLOSE', 'EXPIRED'].includes(data.status)
                                || (!isNil(emailSendResponse) && !isEmpty(emailSendResponse))}
                            outlined
                            label={__('Invia Sollecito', 'gepafin')}
                            icon="pi pi-send"
                        />
                        <Button
                            type="button"
                            onClick={openExtendResponseTimeDialog}
                            disabled={isLoadingExtendingTime || ['CLOSE'].includes(data.status)}
                            outlined
                            label={__('Estendi Scadenza', 'gepafin')}
                            icon="pi pi-stopwatch"
                        />
                        <Button
                            type="button"
                            onClick={() => doUpdateAmendment()}
                            disabled={isAsyncRequest || ['CLOSE', 'AWAITING', 'EXPIRED'].includes(data.status)}
                            label={__('Salva bozza', 'gepafin')}
                            icon="pi pi-save" iconPos="right"/>
                        <Button
                            type="button"
                            onClick={openCloseAmendmentDialog}
                            disabled={isAsyncRequest || ['CLOSE', 'EXPIRED'].includes(data.status)}
                            label={__('Chiudi Soccorso Istruttorio', 'gepafin')}
                            icon="pi pi-times" iconPos="right"/>
                    </div>
                    <div className="appPageSection__actions">
                        <SoccorsoResendEmails
                            emailsData={emailSendResponse}
                            setDataEmailsSoccorso={updateEmailSendResponses}/>
                    </div>
                </div>

            </div>

            <Dialog
                visible={isVisibleExtendTimeDialog}
                modal
                header={headerExtendRespDialog}
                footer={footerExtendRespDialog}
                style={{ maxWidth: '600px', width: '100%' }}
                onHide={hideExtendRespDialog}>
                <div className="appForm__field">
                    <label
                        className={classNames({ 'p-error': isEmpty(extendedTime) })}>
                        {__('Giorni', 'gepafin')}*
                    </label>
                    <InputNumber
                        keyfilter="int"
                        disabled={['CLOSE'].includes(data.status)}
                        value={extendedTime}
                        showButtons
                        onChange={(e) => setExtendedTime(e.value)}/>
                </div>
            </Dialog>

            <Dialog
                visible={isVisibleCloseAmendDialog}
                modal
                header={headerCloseAmendDialog}
                footer={footerCloseAmendDialog}
                style={{ maxWidth: '600px', width: '100%' }}
                onHide={hideCloseAmendDialog}>
                <div className="appForm__field">
                    <label>{__('Motivazioni', 'gepafin')}</label>
                    <div style={{ position: 'relative' }} translate="no">
                        <BlockingOverlay shouldDisplay={data.status === 'CLOSE'}/>
                        <Editor
                            value={internalNote}
                            readOnly={['CLOSE', 'EXPIRED'].includes(data.status)}
                            placeholder={__('Digita qui il messagio', 'gepafin')}
                            headerTemplate={header}
                            onTextChange={(e) => setInternalNote(e.htmlValue)}
                            style={{ height: 80 * 3, width: '100%' }}
                        />
                    </div>
                </div>
            </Dialog>
        </div>
    )

}

export default SoccorsoEditInstructorManager;
