import React, { useEffect, useState, useCallback } from 'react';
import { classNames } from 'primereact/utils';
import { pathOr, isEmpty } from 'ramda';
import { wrap } from 'object-path-immutable';
import equal from 'fast-deep-equal';
import { klona } from 'klona';

// tools
import { nonEmptyTables } from '../../../../helpers/validators';

//components
import RenderTable from './RenderTable';
import NumericFormulaCell from './RenderTable/components/NumericFormulaCell';

const Table = ({
                   fieldName,
                   setDataFn,
                   label,
                   register,
                   errors,
                   disabled = false,
                   config = {},
                   defaultValue = [],
                   tableColumns = []
               }) => {
    const [columnsCfg, setColumnsCfg] = useState([]);
    const [rowsCfg, setRowsCfg] = useState([]);
    const [columns, setColumns] = useState([]);
    const [lastRow, setLastRow] = useState([]);
    const [tableValue, setTableValue] = useState(null);

    const updateValue = useCallback((data) => {
        setTableValue(data);
        setDataFn(fieldName, data, { shouldValidate: true });
    }, [tableValue, defaultValue]);

    const properConfig = (config) => {
        let newConfig = klona(config);
        if (config.validate && config.validate.nonEmptyTables) {
            newConfig = wrap(newConfig)
                .set(['validate', 'nonEmptyTables'], (v) => nonEmptyTables(v, tableColumns))
                .value();
        }

        return newConfig;
    }

    useEffect(() => {
        let newColumns = columnsCfg.map((o) => {
            const item = {
                accessorKey: o.name,
                header: () => o.label,
                footer: (props) => props.column.id,
                meta: {
                    predefined: o.predefined,
                    enableFormula: o.enableFormula,
                    fieldtype: o.fieldtype
                }
            }

            if (o.enableFormula || o.fieldtype === 'numeric') {
                item.cell = NumericFormulaCell;
            } else {
                item.cell = (info) => info.getValue();
            }

            return item;
        });

        setColumns(newColumns);
    }, [columnsCfg, disabled]);


    useEffect(() => {
        const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
        const obj = stateFieldData
            .reduce((acc, cur) => {
                acc[cur.name] = ''
                return acc;
            }, {});
        let rowsData = pathOr([obj], ['rowsData'], tableColumns);
        rowsData = isEmpty(rowsData) ? [obj] : rowsData;
        setColumnsCfg(stateFieldData);
        setRowsCfg({ rows: rowsData, total: 0 });

        let lastRowData = stateFieldData.reduce((acc, cur) => {
            const value = cur.enableFormula ? cur.lastRowFormula : (cur.lastRowText ? cur.lastRowText : '');
            acc.push({ [cur.name]: value });
            return acc;
        }, []);

        const lastRowValues = lastRowData
            .map(o => {
                const values = Object.values(o);
                return values[0];
            })
            .filter(v => !isEmpty(v));

        setLastRow(!isEmpty(lastRowValues) ? lastRowData : []);
    }, [tableColumns]);

    // Saved data (defaultValue) takes priority over template defaults (rowsCfg).
    // Using a single effect for both so the second render caused by rowsCfg changing
    // doesn't overwrite the saved data that was just loaded from the API.
    useEffect(() => {
        const next = (defaultValue && !isEmpty(defaultValue)) ? defaultValue : rowsCfg;
        if (!equal(tableValue, next)) {
            setTableValue(next);
        }
    }, [rowsCfg, defaultValue]); // eslint-disable-line react-hooks/exhaustive-deps

    useEffect(() => {
        register(fieldName, properConfig(config));
    }, []); // eslint-disable-line react-hooks/exhaustive-deps

    return (
        <>
            <label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
                {label}{config.required || config.isRequired || (config.validate && config.validate.nonEmptyTables)
                ? <span className="appForm__field--required">*</span> : null}
            </label>
            {tableValue
                ? <div style={{ width: '100%', overflow: 'auto' }}>
                    <RenderTable
                        columnsCfg={columns}
                        tableValue={tableValue}
                        lastRowCfg={lastRow}
                        setTableValueFn={updateValue}
                        disabled={disabled}/>
                </div> : null}
        </>)
}

export default Table;