import React, { useEffect, useState, useRef } from 'react';
import { __ } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { klona } from 'klona';
import { isEmpty, pathOr } from 'ramda';

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

// components
import FormBuilder from './components/FormBuilder';
import { Button } from 'primereact/button';
import { ConfirmPopup, confirmPopup } from 'primereact/confirmpopup';
import { InputText } from 'primereact/inputtext';
import { Toast } from 'primereact/toast';
import { ConfirmDialog } from 'primereact/confirmdialog';
import { Messages } from 'primereact/messages';

// tools
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';

// api
import FormsService from '../../service/forms-service';
import BandoService from '../../service/bando-service';
import DocumentCategoryService from '../../service/document-category-service';

// TODO temp data
//import { elementItems } from '../../tempData';

const BandoFormsEdit = () => {
    const { id, formId } = useParams();
    const navigate = useNavigate();
    const [formName, setFormName] = useState('');
    const [visibleConfirmation, setVisibleConfirmation] = useState(false);
    const [bandoStatus, setBandoStatus] = useState('');
    const isAsyncRequest = useStoreValue('isAsyncRequest');
    const formMsgs = useRef(null);
    const toast = useRef(null);

    const getBandoId = () => {
        const parsed = parseInt(id)
        return !isNaN(parsed) ? parsed : 0;
    }

    const goBack = () => {
        const bandoId = getBandoId();
        navigate(`/bandi/${bandoId}/forms`);
    }

    const doSave = (shouldRedirect = false) => {
        if (formMsgs.current) {
            formMsgs.current.clear();
        }

        const content = storeGet('formElements');

        if (isEmpty(formName) || isEmpty(content)) {
            if (isEmpty(formName)) {
                if (formMsgs.current) {
                    formMsgs.current.show([
                        {
                            id: '99',
                            sticky: true, severity: 'error', summary: '',
                            detail: __('Nome di form è obligatorio.', 'gepafin'),
                            closable: true
                        }
                    ]);
                }
            }

            if (isEmpty(content)) {
                if (formMsgs.current) {
                    formMsgs.current.show([
                        {
                            id: '99',
                            sticky: true, severity: 'error', summary: '',
                            detail: __('Devi aggiungere almeno uno campo.', 'gepafin'),
                            closable: true
                        }
                    ]);
                }
            }
        }

        const bandoId = getBandoId();
        const parsedFormId = parseInt(formId);
        const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
        const formData = {
            label: formName,
            content
        }

        storeSet('setAsyncRequest');
        if (bandoFormId === 0) {
            FormsService.createFormForCall(
                bandoId,
                formData,
                (data) => formCreateCallback(data, shouldRedirect),
                errFormCreateCallback
            );
        } else {
            FormsService.updateForm(
                bandoFormId,
                formData,
                (data) => formCreateCallback(data, shouldRedirect),
                errFormCreateCallback,
                [['forceDeleteFlow', false]]
            );
        }
    }

    const formCreateCallback = (data, shouldRedirect) => {
        if (data.status === 'SUCCESS') {
            const bandoId = getBandoId();
            storeSet('unsetAsyncRequest');

            if (shouldRedirect) {
                navigate(`/bandi/${bandoId}/forms/${data.data.id}/preview`);
                return;
            }
            if (data.data.id) {
                navigate(`/bandi/${bandoId}/forms/${data.data.id}`);
            }
            if (toast.current) {
                toast.current.show({
                    severity: 'success',
                    summary: '',
                    detail: __('Il form è stato aggiornato correttamente!', 'gepafin')
                });
            }
        }
    }

    const errFormCreateCallback = (data) => {
        storeSet('unsetAsyncRequest');
        if (data.status === 'BAD_REQUEST') {
            setVisibleConfirmation(true);
        } else {
            if (toast.current) {
                toast.current.show({
                    severity: 'error',
                    summary: '',
                    detail: data.message
                });
            }
        }
    }

    const acceptModification = () => {
        const content = storeGet('formElements');
        const parsedFormId = parseInt(formId);
        const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
        const formData = {
            label: formName,
            content
        }

        storeSet('setAsyncRequest');

        FormsService.updateForm(
            bandoFormId,
            formData,
            (data) => formCreateCallback(data, false),
            errFormCreateCallback,
            [['forceDeleteFlow', true]]
        );
    }

    const rejectModification = () => {
        setVisibleConfirmation(false);
    }

    const openPreview = () => {
        if ('PUBLISH' !== bandoStatus) {
            doSave(true);
        } else {
            const bandoId = getBandoId();
            const parsedFormId = parseInt(formId)
            const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
            navigate(`/bandi/${bandoId}/forms/${bandoFormId}/preview`);
        }
    }

    const confirmDelete = (event) => {
        confirmPopup({
            target: event.currentTarget,
            message: __('Sei sicuro di cancellare questo form?', 'gepafin'),
            acceptLabel: __('Si', 'gepafin'),
            icon: 'pi pi-info-circle',
            defaultFocus: 'reject',
            acceptClassName: 'p-button-danger',
            accept: doDelete,
            reject: () => {
            }
        });
    };

    /*const doPublish = () => {
        console.log('doPublish');
    }*/

    const doDelete = () => {
        storeSet('setAsyncRequest');
        FormsService.deleteForm(formId, formDeleteCallback, errFormDeleteCallback)
    }

    const formDeleteCallback = (data) => {
        if (data.status === 'SUCCESS') {
            const bandoId = getBandoId();
            navigate(`/bandi/${bandoId}/forms`);
        }
        storeSet('unsetAsyncRequest');
    }

    const errFormDeleteCallback = (data) => {
        storeSet('unsetAsyncRequest');
    }

    const getElementItemsCallback = (data) => {
        if (data.status === 'SUCCESS') {
            /*storeSet('elementItems', elementItems
                .filter(o => o.id !== 22)
                .sort((a, b) => a.sortOrder - b.sortOrder));*/
            storeSet('elementItems', data.data
                //.filter(o => o.id !== 22 && o.name !== 'spreadsheet')
                .sort((a, b) => a.sortOrder - b.sortOrder));
        }
        storeSet('unsetAsyncRequest');
    }

    const errGetElementItemsCallback = () => {
        storeSet('unsetAsyncRequest');
    }

    const getFormCallback = (data) => {
        if (data.status === 'SUCCESS') {
            storeSet('formId', data.data.id);
            storeSet('formLabel', data.data.label);
            setFormName(data.data.label);
            setBandoStatus(data.data.callStatus);
            const elements = klona(data.data.content);
            storeSet('formElements', elements);
        }
        storeSet('unsetAsyncRequest');
    }

    const errGetFormCallbacks = (data) => {
        set404FromErrorResponse(data);
        storeSet('unsetAsyncRequest');
    }

    const getBandoCallback = (data) => {
        if (data.status === 'SUCCESS') {
            setBandoStatus(data.data.status);
            const criteria = pathOr([], ['data', 'criteria'], data);
            const criteriaOptions = criteria.map(o => ({ value: o.id, label: o.value }));
            storeSet('bandoCriteria', criteriaOptions);
        }
    }

    const errGetBandoCallback = (data) => {
        set404FromErrorResponse(data);
    }

    const getCategories = (resp) => {
        if (resp.status === 'SUCCESS') {
            storeSet('documentCategories', resp.data.map(o => ({ value: o.id, label: o.description })));
        }
    }

    const errGetCategories = () => {
    }

    useEffect(() => {
        const bandoId = getBandoId();
        const parsedFormId = parseInt(formId)
        const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;

        storeSet('setAsyncRequest');
        FormsService.getElementItems(getElementItemsCallback, errGetElementItemsCallback);

        if (bandoFormId) {
            storeSet('setAsyncRequest');
            FormsService.getFormById(bandoFormId, getFormCallback, errGetFormCallbacks);
        }
        if (bandoId) {
            BandoService.getBando(bandoId, getBandoCallback, errGetBandoCallback);
        }

        return () => {
            storeSet('formId', 0);
            storeSet('formLabel', '');
            storeSet('formElements', []);
            storeSet('bandoCriteria', []);
            storeSet('activeElement', '');
            storeSet('selectedElement', '');
        }
    }, [id, formId]);

    useEffect(() => {
        DocumentCategoryService.getCategories(getCategories, errGetCategories)
    }, []);

    return (
        <div className="appPage">
            <div className="appPage__pageHeader">
                <h1>{__('Editor del Form', 'gepafin')}</h1>
                <p>
                    {__('Imposta gli elementi del tuo Form.', 'gepafin')}
                </p>
            </div>

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

            <Messages ref={formMsgs}/>
            <ConfirmDialog
                group="declarative"
                visible={visibleConfirmation}
                onHide={() => setVisibleConfirmation(false)}
                message={__('Le modifiche al modulo influiscono sul flusso precedentemente creato, quindi deve essere ricreato. Confermi le modifiche?', 'gepafin')}
                header={__('Conferma le modifiche', 'gepafin')}
                icon="pi pi-exclamation-triangle"
                accept={acceptModification}
                acceptLabel={__('Si', 'gepafin')}
                reject={rejectModification}
                style={{ maxWidth: '500px' }}/>

            <div className="appForm__field">
                <label htmlFor="label">{__('Assegna un nome a questo form', 'gepafin')}*</label>
                <InputText
                    id="label"
                    value={formName}
                    placeholder=""
                    onChange={(e) => setFormName(e.target.value)}
                    aria-describedby="label-help"/>
            </div>

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

            <div className="appPageSection">
                <DndProvider backend={HTML5Backend}>
                    <FormBuilder callStatus={bandoStatus} context="application"/>
                </DndProvider>
            </div>

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

            <Toast ref={toast}/>
            <div className="appPageSection">
                <div className="appPageSection__actions">
                    <Button
                        onClick={goBack}
                        outlined
                        label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" iconPos="left"/>
                    <Button
                        onClick={() => doSave()}
                        disabled={isAsyncRequest}
                        label={__('Salva progressi', 'gepafin')} icon="pi pi-save" iconPos="right"/>
                    <Button
                        outlined
                        onClick={openPreview}
                        disabled={isAsyncRequest}
                        label={__('Visualizza Anteprima Beneficiario', 'gepafin')} icon="pi pi-image" iconPos="right"/>
                    {/*<Button
                        disabled={true}
                        onClick={doPublish}
                        label={__('Pubblica', 'gepafin')}/>*/}
                </div>
                <div className="appPageSection__actions">
                    <ConfirmPopup/>
                    <Button
                        onClick={confirmDelete}
                        disabled={isAsyncRequest || 'PUBLISH' === bandoStatus}
                        severity="danger"
                        label={__('Cancella', 'gepafin')} icon="pi pi-trash" iconPos="right"/>
                </div>
            </div>
        </div>
    )

}

export default BandoFormsEdit;