import React, { useState, useEffect, useRef, useMemo } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import { useParams } from 'react-router-dom';
import { head, is, pluck, isEmpty, pathOr, isNil, uniqBy } from 'ramda';
import { useForm } from 'react-hook-form';
import 'quill/dist/quill.core.css';
import { wrap } from 'object-path-immutable';
import { evaluate } from 'mathjs';
import equal from 'fast-deep-equal';
import { klona } from 'klona';

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

// api
import ApplicationService from '../../service/application-service';
import CompanyDocumentsService from '../../service/company-documents-service';

// tools
import {
    isPIVA,
    isCodiceFiscale,
    isCAP,
    isIBAN,
    isEmail,
    isEmailPEC,
    isUrl,
    isMarcaDaBollo, minChecks, maxChecks, nonEmptyTables, createSpreadsheetValidator
} from '../../helpers/validators';
import renderHtmlContent from '../../helpers/renderHtmlContent';
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import getFormatedFileSizeText from '../../helpers/getFormatedFileSizeText';
import renderWithDataVars from '../../helpers/renderWithDataVars';
import getTokens from '../../helpers/getTokens';
import formatDateString from '../../helpers/formatDateString';
import isDateTimeInPast from '../../helpers/isDateTimeInPast';
import parseCommaDecimal from '../../helpers/parseCommaDecimal';

// components
import { Skeleton } from 'primereact/skeleton';
import { Button } from 'primereact/button';
import FormField from '../../components/FormField';
import { Toast } from 'primereact/toast';
import { Messages } from 'primereact/messages';
import ApplicationSteps from './ApplicationSteps';
import BlockingOverlay from '../../components/BlockingOverlay';
import { Dialog } from 'primereact/dialog';
import FileuploadApplicationSignedPdf from '../../components/FileuploadApplicationSignedPdf';

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

const REACT_APP_HUB_ID = process.env.REACT_APP_HUB_ID;

const BandoApplication = () => {
    const antiMoneyLaundryCalls = useStoreValue('antiMoneyLaundryCalls');
    const chosenCompanyId = useStoreValue('chosenCompanyId');
    const { id } = useParams();
    const [isExpired, setIsExpired] = useState(false);
    const [formData, setFormData] = useState([]);
    const [formInitialData, setFormInitialData] = useState(null);
    const [bandoTitle, setBandoTitle] = useState('');
    const [bandoId, setBandoId] = useState(0);
    const [formId, setFormId] = useState('');
    const [totalSteps, setTotalSteps] = useState(0);
    const [visibleConfirmation, setVisibleConfirmation] = useState(false);
    const [applicationStatus, setApplicationStatus] = useState('');
    const [activeStep, setActiveStep] = useState(1);
    const [signedPdfFile, setSignedPdfFile] = useState([]);
    const [companyDocs, setCompanyDocs] = useState([]);
    const [personalDocs, setPersonalDocs] = useState([]);
    const [isRequestForApplData, setIsRequestForApplData] = useState(false);
    const isAsyncRequest = useStoreValue('isAsyncRequest');
    const previousStatus = useRef('');
    const toast = useRef(null);
    const formMsgs = useRef(null);
    const {
        control,
        handleSubmit,
        formState: { errors },
        setValue,
        trigger,
        register,
        getValues,
        watch,
        reset
    } = useForm({
        defaultValues: useMemo(() => {
            return formInitialData ? formInitialData : {}
        }, [formInitialData]),
        mode: 'onChange'
    });
    const validationFns = {
        isPIVA,
        isCodiceFiscale,
        isCAP,
        isIBAN,
        isEmail,
        isEmailPEC,
        isUrl,
        isMarcaDaBollo,
        minChecks,
        maxChecks,
        nonEmptyTables
    }
    const activeStepIndex = activeStep - 1;
    const values = getValues();
    const formValues = watch();


    const onValidate = () => {
        saveDraft('VALIDATE');
    };

    const onSubmit = () => {
        const applId = getApplicationId();
        storeSet('setAsyncRequest');
        formMsgs.current.clear();

        ApplicationService.updateStatusApplication(applId, {}, submitApplicationCallback, errSubmitApplicationCallback, [
            ['status', 'SUBMIT']
        ]);
    };

    const submitApplicationCallback = (data) => {
        if (data.status === 'SUCCESS') {
            if (data.data.status) {
                setApplicationStatus(data.data.status); // ask why not 'applicationStatus'?
            }
        }
        storeSet('unsetAsyncRequest');
    }

    const errSubmitApplicationCallback = (data) => {
        storeSet('unsetAsyncRequest');
        if (data.status === 'VALIDATION_ERROR') {
            if (formMsgs.current) {
                formMsgs.current.show([
                    {
                        id: '99',
                        sticky: true, severity: 'error', summary: '',
                        detail: data.data.join(', '),
                        closable: true
                    }
                ]);
            }
        } else if (data.status === 'EXCEPTION_ERROR') {
            if (formMsgs.current) {
                formMsgs.current.show([
                    {
                        id: '99',
                        sticky: true, severity: 'error', summary: '',
                        detail: data.message,
                        closable: true
                    }
                ]);
            }
        } else if (data.status === 'BAD_REQUEST') {
            if (formMsgs.current) {
                formMsgs.current.show([
                    {
                        id: '99',
                        sticky: true, severity: 'error', summary: '',
                        detail: data.message,
                        closable: true
                    }
                ]);
                toast.current.show({
                    severity: 'error',
                    summary: '',
                    detail: data.message
                });
            }
        } else {
            set404FromErrorResponse(data);
        }
    }

    const validateApplicationCallback = (data) => {
        if (data.status === 'SUCCESS') {
            if (data.data.status) {
                setApplicationStatus(data.data.status);
            }
        }
        storeSet('unsetAsyncRequest');
    }

    const errValidateApplicationCallback = (data) => {
        if (data.status === 'VALIDATION_ERROR') {
            if (formMsgs.current) {
                formMsgs.current.show([
                    {
                        id: '99',
                        sticky: true, severity: 'error', summary: '',
                        detail: data.data.join(' '),
                        closable: true
                    }
                ]);
            }
        } else {
            if (toast.current) {
                toast.current.show({
                    severity: 'error',
                    summary: '',
                    detail: data.message
                });
            }
        }
        storeSet('unsetAsyncRequest');
    }

    const saveDraft = (saveAndMove = '') => {
        trigger();

        const formValues = getValues();
        const usedFieldsIds = pluck('id', formData);
        const newFormValues = Object.keys(formValues)
            .filter(v => usedFieldsIds.includes(v))
            .reduce((acc, cur) => {
                const formField = head(formData.filter(o => o.id === cur));
                let fieldVal = formValues[cur];

                if (formValues[cur] && formValues[cur].toISOString) {
                    fieldVal = formatDateString(formValues[cur]);
                }

                fieldVal = isEmpty(fieldVal) ? null : fieldVal;
                if (formField && ['fileupload', 'fileselect'].includes(formField.name)) {
                    fieldVal = is(Array, fieldVal) ? fieldVal.map(o => o.id).join(',') : null;
                }
                acc.push({
                    'fieldId': cur,
                    'fieldValue': fieldVal
                });
                return acc;
            }, []);
        const submitData = {
            formFields: newFormValues
        }

        if (formId) {
            const applId = getApplicationId();
            storeSet('setAsyncRequest');

            if (formMsgs.current) {
                formMsgs.current.clear();
            }

            ApplicationService.saveDraft(applId, submitData, (data) => saveDraftCallback(data, saveAndMove), errSaveDraftCallback, [
                ['formId', formId]
            ]);
        }
    }

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

    const saveDraftCallback = (data, saveAndMove = '') => {
        storeSet('unsetAsyncRequest');
        if (data.status === 'SUCCESS') {
            if (toast.current) {
                toast.current.show({
                    severity: 'success',
                    summary: '',
                    detail: __('Salvato!', 'gepafin')
                });
            }
            if (!isEmpty(saveAndMove) && is(String, saveAndMove)) {
                if (['NEXT', 'PREVIOUS'].includes(saveAndMove)) {
                    storeSet('setAsyncRequest');
                    ApplicationService.getApplicationForm(data.data.id, getApplFormCallback, errGetApplFormCallbacks, [
                        ['formId', formId],
                        ['companyId', chosenCompanyId],
                        ['action', saveAndMove]
                    ]);
                } else if (['VALIDATE'].includes(saveAndMove)) {
                    const applId = getApplicationId();
                    storeSet('setAsyncRequest');
                    formMsgs.current.clear();

                    ApplicationService.validateApplication(applId, {}, validateApplicationCallback, errValidateApplicationCallback);
                }
            } else {
                ApplicationService.getApplicationForm(data.data.id, getStatusCheckCallback, errGetStatusCheckCallbacks, [
                    ['companyId', chosenCompanyId]
                ]);
            }
        }
    }

    const errSaveDraftCallback = (data) => {
        storeSet('unsetAsyncRequest');
        if (data.status === 'VALIDATION_ERROR') {
            if (formMsgs.current) {
                formMsgs.current.show([
                    {
                        id: '99',
                        sticky: true, severity: 'error', summary: '',
                        detail: data.data.join(' '),
                        closable: true
                    }
                ]);
            }
        } else if (data.status === 'EXCEPTION_ERROR') {
            if (formMsgs.current) {
                formMsgs.current.show([
                    {
                        id: '99',
                        sticky: true, severity: 'error', summary: '',
                        detail: data.message,
                        closable: true
                    }
                ]);
            }
        } else {
            set404FromErrorResponse(data);
        }
    }

    const goBackward = () => {
        saveDraft('PREVIOUS');
    }

    const goForward = () => {
        saveDraft('NEXT');
    }

    const getApplFormCallback = (data) => {
        if (data.status === 'SUCCESS') {
            setBandoTitle(data.data.callTitle);
            setBandoId(data.data.callId);
            setFormData(data.data.applicationFormResponse.content);
            setFormId(data.data.formId);
            setTotalSteps(data.data.totalFormSteps);
            //setCompletedSteps(data.data.completedSteps);
            setApplicationStatus(data.data.applicationStatus)
            setActiveStep(data.data.currentStep);
            const isCallExpired = isDateTimeInPast(data.data.callEndDate, data.data.callEndTime);
            setIsExpired(isCallExpired);

            const chosenCompanyId = data.data.companyId;
            const companies = storeGet('companies');
            const company = head(companies.filter(o => o.id === chosenCompanyId));
            let formDataInitial = {};
            let dynamicData = {
                company: {},
                user: {},
                custom: {}
            };

            if (company) {
                dynamicData = Object.keys(company).reduce((acc, cur) => {
                    if ([
                        'companyName', 'vatNumber', 'codiceFiscale', 'address', 'phoneNumber',
                        'city', 'province', 'cap', 'country', 'pec', 'email', 'contactName', 'contactEmail',
                        'codiceAteco'
                    ].includes(cur)) {
                        acc.company[cur] = company[cur];
                    }
                    return acc;
                }, dynamicData);
            }

            const userData = storeGet('userData');
            Object.keys(userData).reduce((acc, cur) => {
                if ([
                    'email', 'firstName', 'lastName', 'phoneNumber', 'codiceFiscale'
                ].includes(cur)) {
                    acc.user[cur] = userData[cur];
                }
                if (['dateOfBirth'].includes(cur)) {
                    acc.user[cur] = new Date(userData[cur]);
                }
                return acc;
            }, dynamicData);

            const userFullName = `${userData.firstName} ${userData.lastName}`;
            dynamicData = wrap(dynamicData).set(['custom', 'userFullName'], userFullName).value();
            const legalRepresentantName = company.isLegalRepresentant ? userFullName : '';
            dynamicData = wrap(dynamicData).set(['custom', 'legalRepresentant'], legalRepresentantName).value();

            if (data.data.applicationFormResponse.content) {
                // eslint-disable-next-line array-callback-return
                data.data.applicationFormResponse.content.map((o) => {
                    if (o.dynamicData && !isEmpty(o.dynamicData)) {
                        formDataInitial[o.id] = pathOr('', o.dynamicData.split('.'), dynamicData);
                    }
                });
            }

            if (data.data.applicationFormResponse.formFields) {
                const submitData = data.data.applicationFormResponse.formFields.map((o) => ({
                    fieldId: o.fieldId,
                    fieldValue: o.fieldValue
                }));
                formDataInitial = submitData.reduce((acc, cur) => {
                    if (cur.fieldValue) {
                        acc[cur.fieldId] = cur.fieldValue;
                    }
                    return acc;
                }, formDataInitial);
            }

            reset(formDataInitial);
            setFormInitialData(formDataInitial);
        }
        storeSet('unsetAsyncRequest');
        setIsRequestForApplData(false);
    }

    const errGetApplFormCallbacks = (data) => {
        storeSet('unsetAsyncRequest');
        setIsRequestForApplData(false);
        if (data.status === 'VALIDATION_ERROR') {
            if (toast.current) {
                toast.current.show({
                    severity: 'error',
                    summary: '',
                    detail: data.message
                });
            }
        } else {
            set404FromErrorResponse(data);
        }
    }

    const getStatusCheckCallback = (data) => {
        if (data.status === 'SUCCESS') {
            //setCompletedSteps(data.data.completedSteps);
        }
    }

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

    const actionBtns = <div className="appPageSection__actions">
        {activeStep > 1 && activeStep <= totalSteps
            ? <Button
                type="button"
                disabled={'SUBMIT' === applicationStatus || isExpired}
                onClick={goBackward}
                label={__('Vai indietro', 'gepafin')}
                icon="pi pi-arrow-left"
                iconPos="left"/> : null}
        <Button
            type="button"
            disabled={isAsyncRequest || 'SUBMIT' === applicationStatus || isExpired}
            onClick={saveDraft}
            outlined
            label={__('Salva bozza', 'gepafin')} icon="pi pi-save" iconPos="right"/>
        {activeStep < totalSteps
            ? <Button
                type="button"
                disabled={'SUBMIT' === applicationStatus || isExpired}
                onClick={goForward}
                label={__('Vai avanti', 'gepafin')}
                icon="pi pi-arrow-right"
                iconPos="right"/> : null}
        <Button
            type="button"
            disabled={'SUBMIT' === applicationStatus || isExpired}
            onClick={onValidate}
            label={__('Convalida per la firma', 'gepafin')}
            icon="pi pi-check"
            iconPos="right"/>
    </div>

    const onDownloadApplicationPdf = () => {
        const applId = getApplicationId();
        storeSet('setAsyncRequest');

        ApplicationService.downloadApplicationPdf(applId, {}, getPdfCallback, errPdfCallback);
    }

    const getPdfCallback = (data) => {
        const applId = getApplicationId();
        const pdfFile = new Blob([data], { type: 'application/octet-stream' })
        const url = window.URL.createObjectURL(pdfFile);
        const link = document.createElement('a');
        link.href = url;
        link.setAttribute('download', `application-${applId}.pdf`);
        document.body.appendChild(link);
        link.click();
        link.remove();
        storeSet('unsetAsyncRequest');
    }

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

    const getSignedPdfCallback = (data) => {
        if (data.status === 'SUCCESS') {
            setSignedPdfFile([data.data]);
        }
        storeSet('unsetAsyncRequest');
    }

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

    const handleSetSignedDocumentFromFileupload = (fieldName, stateFieldData) => {
        setSignedPdfFile(stateFieldData);

        if (!isEmpty(stateFieldData)) {
            setApplicationStatus('READY');
        }
    }

    const doChangeToDraft = () => {
        const applId = getApplicationId();
        storeSet('setAsyncRequest');
        formMsgs.current.clear();

        ApplicationService.updateStatusApplication(applId, {}, changeToDraftCallback, errChangeToDraftCallback, [
            ['status', 'DRAFT']
        ]);
    };

    const changeToDraftCallback = (data) => {
        if (data.status === 'SUCCESS') {
            if (data.data.status) {
                setApplicationStatus(data.data.status);
            }
        }
        storeSet('unsetAsyncRequest');
    }

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

    // TODO hardcoded for now
    const signedDocMime = bandoId === 10
        ? ['.p7m,application/pkcs7-mime,application/x-pkcs7-mime', '.pdf,application/pdf']
        : ['.p7m,application/pkcs7-mime,application/x-pkcs7-mime'];
    const signedDocValidationString = bandoId === 10
        ? ['.p7m', '.pdf']
        : ['.p7m'];

    const getDocsCallback = (resp, type) => {
        if (resp.status === 'SUCCESS') {
            const filteredPersonal = getFormattedDocsData(resp.data.filter(o => o.type === 'PERSONAL_DOCUMENT'));
            setPersonalDocs(uniqBy((o) => o.id, filteredPersonal));
            const filteredCompany = getFormattedDocsData(resp.data.filter(o => o.type === 'COMPANY_DOCUMENT'));
            setCompanyDocs(uniqBy((o) => o.id, filteredCompany));
        }
    }

    const errDocsGetCallbacks = () => {
    }

    const getFormattedDocsData = (data) => {
        return data.map((d) => {
            d.callEndDate = is(String, d.callEndDate) ? new Date(d.callEndDate) : (d.callEndDate ? d.callEndDate : '');
            return d;
        });
    };

    useEffect(() => {
        let updatedFormValues = klona(formValues);
        let context = {};

        // eslint-disable-next-line array-callback-return
        formData.map((o) => {
            const variable = head(o.settings.filter(o => o.name === 'variable'));
            const formula = head(o.settings.filter(o => o.name === 'formula'));
            const isRequestedAmount = head(o.settings.filter(o => o.name === 'isRequestedAmount'));

            if (formula && !isEmpty(formula.value)) {
                try {
                    context = getTokens(formula.value)
                        .filter(v => !['false', 'null', 'true'].includes(v))
                        .reduce((acc, cur) => {
                            acc[cur] = isNil(context[cur]) ? 0 : parseCommaDecimal(context[cur]);
                            return acc;
                        }, context);
                } catch {
                    console.error('Error in formula', formula)
                    context = {}
                }

                const mathFormula = renderWithDataVars(formula.value, context);
                try {
                    updatedFormValues[o.id] = evaluate(mathFormula);
                } catch (e) {
                    console.log('Error in math formula: "', mathFormula, '"', e.message);
                    updatedFormValues[o.id] = 0;
                }
            }

            if (variable && !isEmpty(variable.value)) {
                context[variable.value[0]] = 'criteria_table' === o.name
                    ? pathOr(0, [o.id, 'total'], updatedFormValues)
                    : pathOr(0, [o.id], updatedFormValues);
            }

            if (REACT_APP_HUB_ID !== 't7jh5wfg9QXylNaTZkPoE' && antiMoneyLaundryCalls.includes(bandoId) && isRequestedAmount && isRequestedAmount.value) {
                updatedFormValues[o.id] = 100;
            }
        });

        if (!isEmpty(updatedFormValues) && !equal(updatedFormValues, formValues)) {
            reset(updatedFormValues);
        }
    }, [formValues]);

    useEffect(() => {
        if (previousStatus.current === applicationStatus) {
            return
        }

        previousStatus.current = applicationStatus;

        if ('DRAFT' === applicationStatus && !isRequestForApplData) {
            const applId = getApplicationId();

            if (applId) {
                storeSet('setAsyncRequest');
                ApplicationService.getApplicationForm(applId, getApplFormCallback, errGetApplFormCallbacks, [
                    ['companyId', chosenCompanyId]
                ]);
            }
        }

        if ('SUBMIT' === applicationStatus) {
            setVisibleConfirmation(true);
        }

        if (['AWAITING', 'READY', 'SUBMIT'].includes(applicationStatus)) {
            const applId = getApplicationId();

            if (applId) {
                storeSet('setAsyncRequest');
                ApplicationService.getApplicationSignedPdf(applId, getSignedPdfCallback, errSignedPdfCallbacks);
            }
        }
    }, [applicationStatus]);

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

    useEffect(() => {
        const applId = getApplicationId();

        if (applId) {
            storeSet('setAsyncRequest');
            setIsRequestForApplData(true);
            ApplicationService.getApplicationForm(applId, getApplFormCallback, errGetApplFormCallbacks, [
                ['companyId', chosenCompanyId]
            ]);
            CompanyDocumentsService.getCompanyDocuments(chosenCompanyId, getDocsCallback, errDocsGetCallbacks);
        }
    }, [id, chosenCompanyId]);

    return (
        <div className="appPage">
            {!isAsyncRequest
                ? <div className="appPage__pageHeader">
                    <h1>{sprintf(__('Domanda per il Bando: %s', 'gepafin'), bandoTitle)}</h1>
                </div>
                : <>
                    <Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
                    <Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
                </>}

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

            {'DRAFT' === applicationStatus
                ? <ApplicationSteps totalSteps={totalSteps} activeStepIndex={activeStepIndex}/>
                : null}

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

            <Messages ref={formMsgs}/>
            <Toast ref={toast}/>
            <Dialog header={__('Conferma', 'gepafin')}
                    visible={visibleConfirmation}
                    style={{ width: '50vw' }}
                    onHide={() => {
                        if (!visibleConfirmation) return;
                        setVisibleConfirmation(false);
                    }}>
                <p>
                    {REACT_APP_HUB_ID === 't7jh5wfg9QXylNaTZkPoE'
                        ? __('Grazie, la tua domanda è stata inviata correttamente. Entro 24 ore riceverai una email con data, ora e numero di protocollo.', 'gepafin')
                        : __('Grazie, la tua domanda è stata inviata correttamente. Entro 24 ore riceverai una pec con data, ora e numero di protocollo.', 'gepafin')
                    }
                </p>
            </Dialog>

            <div className="appPage__content">
                <BlockingOverlay shouldDisplay={isAsyncRequest}/>
                <form className="appForm" onSubmit={handleSubmit(onValidate)}>
                    {isExpired
                        ? <div className="appPageSection__preview">
                            {__('Il bando è scaduto!', 'gepafin')}
                        </div>
                        : null}

                    {'DRAFT' === applicationStatus
                        ? <div className="appPageSection">
                            {actionBtns}
                        </div> : null}

                    {'DRAFT' === applicationStatus
                        /*|| 'AWAITING' === applicationStatus*/
                        ? formData.map(o => {
                            const isRequestedAmount = head(o.settings.filter(o => o.name === 'isRequestedAmount'));
                            const label = head(o.settings.filter(o => o.name === 'label'));
                            const text = head(o.settings.filter(o => o.name === 'text'));
                            const placeholder = head(o.settings.filter(o => o.name === 'placeholder'));
                            const options = ['fileselect'].includes(o.name)
                                ? { value: [...companyDocs, ...personalDocs] }
                                : head(o.settings.filter(o => o.name === 'options'));
                            let tableColumns = head(o.settings.filter(o => o.name === 'table_columns'));
                            if (!tableColumns) {
                                tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
                            }
                            const template = head(o.settings.filter(s => s.name === 'template'));
                            const step = head(o.settings.filter(o => o.name === 'step'));
                            const mime = head(o.settings.filter(o => o.name === 'mime'));
                            const documentCategories = head(o.settings.filter(o => o.name === 'documentCategories'));
                            const formula = head(o.settings.filter(o => o.name === 'formula'));
                            let mimeValue = '';

                            if (mime) {
                                mimeValue = mime.value.map(o => o.code ? o.code : o.ext);
                            }

                            const validations = Object.keys(o.validators).reduce((acc, cur) => {
                                if (o.validators[cur]) {
                                    if (['minLength', 'maxLength', 'maxSize'].includes(cur)) {
                                        acc[cur] = parseInt(o.validators[cur]);
                                    } else if (['min', 'max'].includes(cur)) {
                                        acc[cur] = parseFloat(o.validators[cur]);
                                    } else if ('pattern' === cur) {
                                        acc[cur] = new RegExp(o.validators[cur]);
                                    } else if ('isRequired' === cur) {
                                        //acc[cur] = o.validators[cur];
                                        acc['required'] = true;
                                    } else if ('custom' === cur && validationFns[o.validators[cur]]) {
                                        if (!acc.validate) {
                                            acc.validate = {};
                                        }
                                        acc.validate[o.validators[cur]] = validationFns[o.validators[cur]];
                                    }
                                }

                                return acc;
                            }, {});

                            if (o.name === 'spreadsheet') {
                                const gepafin = template?.value?.gepafin;
                                if (gepafin?.validationCells?.length) {
                                    if (!validations.validate) validations.validate = {};
                                    validations.validate.spreadsheetInputValid = createSpreadsheetValidator(gepafin);
                                }
                            }

                            /*if (o.name === 'fileselect') {
                                console.log('options::', options)
                            }*/
                            const hideField = REACT_APP_HUB_ID !== 't7jh5wfg9QXylNaTZkPoE' && antiMoneyLaundryCalls.includes(bandoId) && isRequestedAmount && isRequestedAmount.value

                            return ['paragraph'].includes(o.name) && text
                                ? <div key={o.id}>
                                    <div className="ql-editor">
                                        {renderHtmlContent(text.value)}
                                    </div>
                                </div>
                                : <FormField
                                    key={o.id}
                                    additionalClass={hideField ? 'hidden' : ''}
                                    disabled={isExpired}
                                    readOnly={formula && !isEmpty(formula.value)}
                                    type={o.name}
                                    fieldName={o.id}
                                    label={label ? label.value : ''}
                                    placeholder={placeholder ? placeholder.value : ''}
                                    control={control}
                                    register={register}
                                    errors={errors}
                                    defaultValue={values[o.id] ? values[o.id] : ''}
                                    maxFractionDigits={step ? step.value : 0}
                                    accept={mimeValue}
                                    documentCategories={documentCategories ? documentCategories.value : []}
                                    config={validations}
                                    options={options ? options.value : []}
                                    setDataFn={setValue}
                                    saveFormCallback={saveDraft}
                                    sourceId={getApplicationId()}
                                    useGrouping={false}
                                    tableColumns={tableColumns ? tableColumns.value : {}}
                                    template={template ? template.value : null}
                                />
                        })
                        : null}

                    {['AWAITING'].includes(applicationStatus)
                        ? <div className="appPageSection">
                            <Button
                                type="button"
                                disabled={isExpired}
                                outlined
                                onClick={doChangeToDraft}
                                label={__('Ripristina draft', 'gepafin')}
                                icon="pi pi-arrow-left" iconPos="left"/>
                        </div> : null}

                    {['AWAITING', 'READY', 'SUBMIT', 'EVALUATION'].includes(applicationStatus)
                        ? <div className="appPageSection">
                            <div className="appForm__field">
                                <label>
                                    {__('Scarica documento della domanda nel formato PDF', 'gepafin')}
                                </label>
                            </div>
                            <Button
                                type="button"
                                disabled={'SUBMIT' === applicationStatus || isExpired}
                                onClick={onDownloadApplicationPdf}
                                label={__('Scarica PDF', 'gepafin')}
                                icon="pi pi-download"
                                iconPos="right"/>
                        </div> : null}

                    {'AWAITING' === applicationStatus
                        ? <div className="appPageSection">
                            <div className="appForm__field">
                                <label htmlFor="signedPdfFile">
                                    {__('Carica documento della domanda firmato', 'gepafin')}
                                    {` (${signedDocValidationString.join(', ')}) `}
                                    {`(max ${getFormatedFileSizeText(defaultMaxFileSize)})`}
                                </label>
                                <FileuploadApplicationSignedPdf
                                    setDataFn={handleSetSignedDocumentFromFileupload}
                                    fieldName="signedPdfFile"
                                    disabled={!isEmpty(signedPdfFile) || 'AWAITING' !== applicationStatus || isExpired}
                                    defaultValue={is(Array, signedPdfFile) ? signedPdfFile : []}
                                    accept={signedDocMime}
                                    chooseLabel={__('Aggiungi documento', 'gepafin')}
                                    multiple={false}
                                    doctype="document"
                                    applicationId={id}
                                />
                            </div>
                        </div>
                        : null}

                    {['AWAITING', 'READY'].includes(applicationStatus)
                        ? <div className="appPageSection">
                            <Button
                                type="button"
                                disabled={'READY' !== applicationStatus || isExpired}
                                onClick={onSubmit}
                                label={__('Invia', 'gepafin')}
                                icon="pi pi-check"
                                iconPos="right"/>
                        </div> : null}

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

                    {'DRAFT' === applicationStatus
                        ? <div className="appPageSection__hr">
                            <span>{__('Azioni rapide', 'gepafin')}</span>
                        </div> : null}

                    {isExpired
                        ? <div className="appPageSection__preview">
                            {__('Il bando è scaduto!', 'gepafin')}
                        </div> : null}

                    {'DRAFT' === applicationStatus
                        ? <div className="appPageSection">
                            {actionBtns}
                        </div> : null}
                </form>
            </div>
        </div>
    )

}

export default BandoApplication;