import React, { useEffect, useState, useRef } from 'react';
import { classNames } from 'primereact/utils';
import { __ } from '@wordpress/i18n';

// api
import FileUploadService from '../../../../service/file-upload-service';

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

// components
import { FileUpload } from 'primereact/fileupload';
import { Tag } from 'primereact/tag';
import { Button } from 'primereact/button';
import { head, isEmpty } from 'ramda';
import { Messages } from 'primereact/messages';
        

import { defaultMaxFileSize, mimeTypes } from '../../../../configData';
import getFormatedFileSizeText from '../../../../helpers/getFormatedFileSizeText';

const FileuploadAsync = ({
                             fieldName,
                             setDataFn,
                             label,
                             errors,
                             register,
                             defaultValue = [],
                             config = {},
                             infoText = null,
                             accept = ['image/*'],
                             doctype = 'images',
                             maxSize = defaultMaxFileSize,
                             minSize = 1,
                             emptyText = __('Trascina qui il tuo file', 'gepafin'),
                             chooseLabel = __('Aggiungi immagine', 'gepafin'),
                             multiple = false,
                             sourceId = 0,
                             source = 'application',
                             disabled = false
                         }) => {
    // eslint-disable-next-line no-unused-vars
    const [stateFieldData, setStateFieldData] = useState([]);
    const [acceptFormats, setAcceptFormats] = useState('');
    const [formatsForInput, setFormatsForInput] = useState('');
    const inputRef = useRef();
    const messagesRef = useRef(null);

    const customBase64Uploader = (event) => {
        const formData = new FormData()
        const filesToUpload = [];
        const uploadedFiles = inputRef.current ? inputRef.current.getUploadedFiles() : [];
        const currentFiles = stateFieldData;

        for (const file of event.files) {
            const isDuplicate = [...uploadedFiles, ...currentFiles].some(
                (uploadedFile)=>uploadedFile.name === file.name
            );

            if(isDuplicate){
                messagesRef.current.show({
                    severity: 'error',
                    summary: __('Attenzione', 'gepafin'),
                    detail: `Il file con nome "${file.name}" è già stato caricato.`,
                    life: 10000
                });
                
            } else {
                formData.append('file', file)
                filesToUpload.push(file);
            }
            
        }
        if(filesToUpload.length > 0){
            FileUploadService.uploadFile(sourceId, formData, callback, errorCallback, [
                ['documentType', doctype.toUpperCase()],
                ['sourceType', source.toUpperCase()]
            ]);
        } 
    };

    const callback = (data, uploadedFiles) => {
        if (data.status === 'SUCCESS') {
            setStateFieldData(prevState => [...prevState, ...data.data]);
            const currentUploadedFiles = inputRef.current.getUploadedFiles() || [];
            
            inputRef.current.setUploadedFiles([...currentUploadedFiles, ...data.data]);
            inputRef.current.setFiles([]);
            
            setDataFn(fieldName, [...currentUploadedFiles, ...data.data], { shouldValidate: true });
        }
    }

    const errorCallback = (err) => {
        console.log('err', err);
    }

    const itemTemplate = (file) => {
        return (
            <div className="appForm__fileUploadItem">
                <div>
                    <span className="appForm__fileUploadItemName">
                        {file.name}
                    </span>
                </div>
                <div>
                    {file.id ? <Tag value={__('Caricato', 'gepafin')} severity="success"></Tag> : null}
                    {!file.id ? <Tag value={__('In attesa', 'gepafin')} severity="warning"></Tag> : null}
                </div>
                <div>
                    <Button
                        type="button"
                        disabled={disabled}
                        icon="pi pi-times"
                        severity="danger"
                        aria-label={__('Annulla', 'gepafin')}
                        onClick={() => onTemplateRemove(file)}/>
                </div>
            </div>
        );
    };

    const onTemplateRemove = (file) => {
        if (file.id) {
            FileUploadService.deleteFile(
                {},
                (data) => dCallback(data, file.id),
                dErrorCallback,
                [['id', file.id]]
            );
        } else {
            const files = inputRef.current.getFiles()
            const newFiles = files.filter(o => o.lastModified !== file.lastModified && o.name !== file.name);
            inputRef.current.setFiles(newFiles);
        }
    }

    const dCallback = (data, id) => {
        if (data.status === 'SUCCESS') {
            setStateFieldData(prevState => {
                const newFiles = prevState.filter(o => o.id !== id);
                setDataFn(fieldName, newFiles, { shouldValidate: true });
                return newFiles;
            });
        }
    }

    const dErrorCallback = (err) => {
        console.log('err', err);
    }

    const onBeforeDrop = (e) => {
        return !isEmpty(e.dataTransfer.files) ? validateFileInputType(e.dataTransfer.files) : false;
    }

    const onBeforeSelect = (e) => {
        const files = inputRef.current.getFiles();
        const uploadedfiles = inputRef.current.getUploadedFiles();

        if (!multiple && (uploadedfiles.length > 0 || files.length > 0)) {
            return false;
        }

        if (e.originalEvent.target.files) {
            return !isEmpty(e.originalEvent.target.files)
                ? validateFileInputType(e.originalEvent.target.files)
                : false;
        }
    }

    const validateFileInputType = (files) => {
        const MIMEtype = new RegExp(acceptFormats);

        return Array.prototype.every.call(files, function passesAcceptedFormat(file) {
            const fileExtension = `.${file.name.split('.').pop().toLowerCase()}`;
            const fileType = file.type;
            if (file.size === 0) {
                alert('Il file non è valido');
            }
            return file.size > 0 && (MIMEtype.test(fileType) || MIMEtype.test(fileExtension));
        });
    }

    useEffect(() => {
        setStateFieldData(defaultValue);
        register(fieldName, config)
    }, []);

    useEffect(() => {
        if (inputRef.current) {
            inputRef.current.setUploadedFiles(defaultValue);     
        }
        setStateFieldData(defaultValue);
    }, [defaultValue]);

    useEffect(() => {
        const properMime = accept.map
            ? accept
                .map(v => {
                    const found = head(mimeTypes.filter(o => o.code.includes(v)));
                    let res = v;

                    if (found) {
                        res = found.code;
                    }

                    return res;
                }) : [];
        // eslint-disable-next-line no-useless-escape
        setAcceptFormats(properMime.join(',').replace(/\*/g, '.\*').replace(/,/g, '|'));
        setFormatsForInput(properMime.join(','))
    }, [accept]);

    return (
        sourceId && sourceId !== 0
            ? <>
                <Messages ref={messagesRef} /> 
                <label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
                    {label}{config.required ? '*' : null}
                    {acceptFormats ? ' (' + getPropeMimeLabels(accept) + ')' : null}
                    {` (max ${getFormatedFileSizeText(maxSize)})`}
                </label>
                <FileUpload
                    ref={inputRef}
                    disabled={disabled}
                    id={fieldName}
                    name={fieldName}
                    url={'/document/uploadFile'}
                    multiple={multiple}
                    accept={formatsForInput}
                    maxFileSize={maxSize}
                    emptyTemplate={<p>{emptyText}</p>}
                    chooseLabel={chooseLabel}
                    cancelLabel={__('Cancella', 'gepafin')}
                    uploadLabel={__('Carica', 'gepafin')}
                    className={classNames({ 'p-invalid': errors[fieldName] })}
                    itemTemplate={itemTemplate}
                    customUpload
                    onBeforeDrop={onBeforeDrop}
                    onBeforeSelect={onBeforeSelect}
                    uploadHandler={customBase64Uploader}/>
                {infoText ? <small>{infoText}</small> : null}
            </>
            : null
    )
}

export default FileuploadAsync;