import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React, { useState, useRef, useEffect } from 'react';
import Spreadsheet from './ExcelFileComponents/index';
import './ExcelFile.scss';
import Tooltip from '../../Tooltip';
import Icon from '../../Icon';
import Toastify from '../../Toastify';
import { toast } from '../../Toastify/Toastify';
import ExcelContextMenu from '../ExcelContextMenu/ExcelContextMenu';
import Typography from '../../Typography';
import { convertStyleToBackend, convertStyleToFrontend, } from '../dataConversion';
import { checkEmpty } from '../../../utils/checkEmpty/checkEmpty';
import { debounce } from '../../../utils/debounce/debounce';
import classNames from 'classnames';
import { EmptyCell } from './ExcelFileComponents/util';
import MenuOption from '../../MenuOption';
import { isTextTruncated, truncateText, } from '../../../utils/truncateText/truncateText';
const ExcelFile = ({ excelData, contextOption, toolbar = 'show', sheetBar = 'show', rowCount = 26, colCount = 26, sheetHeight = '100%', editable = true, contextHeightPositioning = 0, contextWidthPositioning = 0, onSave = () => Promise.resolve(), onSaveInfoChange, attachmentAction = {
    addAttachment: () => Promise.resolve(''),
    deleteAttachment: () => Promise.resolve(''),
    viewAttachment: () => Promise.resolve(),
}, onSaveDelay = 3000, scroller = false, columnContextEnable = true, rowContextEnable = true, sheetBarContextEnable = true, minimumColumnWidth = 100, disableDeleteOption = false, maxRowLimit = Infinity, maxColLimit = Infinity, maxSheetLimit = Infinity, getActiveCell = () => { }, }) => {
    const menuRef = useRef(null);
    const [sheetNames, setSheetNames] = useState([]);
    const [saveInfo, setSaveInfo] = useState('');
    const [contextMenu, setContextMenu] = React.useState({
        open: false,
        contextType: null,
        options: [
            {
                label: '',
                value: '',
                iconName: '',
                action: () => { },
                disableTooltip: '',
                disable: false,
                visible: false,
            },
        ],
    });
    const [selectedSheet, setSelectedSheet] = useState({ name: 'defaultSheet', index: 0 });
    const [worksheetsData, setWorksheetsData] = useState({ defaultSheet: [[EmptyCell]] });
    const [selectedSheetData, setSelectedSheetData] = useState([[EmptyCell]]);
    const [headerOldNew, setHeaderOldNew] = useState(onSave.length > 1 ? {} : {});
    const [position, setPosition] = useState({
        x: 0,
        y: 0,
    });
    const pageRef = useRef('');
    const workRef = useRef(null);
    const sheetRef = useRef(null);
    const spreadsheetRef = useRef(null);
    const checkVal = (val) => {
        if (val === undefined || val === null) {
            return null;
        }
        return val;
    };
    useEffect(() => {
        const payload = excelData;
        if (payload) {
            const sheetNames = payload.map((e) => e.sheetName);
            setSheetNames(sheetNames);
            if (!checkEmpty(sheetNames.length)) {
                pageRef.current = sheetNames[0] || ''; // Ternary is required, must use ''
                setSelectedSheet({
                    name: sheetNames[0] || '', // Ternary is required, must use ''
                    index: 0,
                });
            }
            const newWorksheetsData = {};
            const newHeaderOldNew = {};
            payload.forEach((sheet) => {
                const sheetName = sheet.sheetName;
                const json = sheet.data;
                const maxRows = Math.max(rowCount, json.length);
                const maxCols = Math.max(colCount, Math.max(...json.map((row) => row.length)));
                let spreadsheetData = Array.from({ length: maxRows }, () => Array(maxCols).fill({
                    value: '',
                    style: EmptyCell.style,
                    readOnly: false,
                    inputType: undefined,
                }));
                json.forEach((row, rowIndex) => {
                    row.forEach((cell, colIndex) => {
                        if (rowIndex < maxRows && colIndex < maxCols) {
                            if (!spreadsheetData[rowIndex]) {
                                spreadsheetData[rowIndex] = [];
                            }
                            spreadsheetData[rowIndex][colIndex] = {
                                value: checkVal(cell.value),
                                style: checkEmpty(cell?.style)
                                    ? EmptyCell.style
                                    : convertStyleToFrontend(cell?.style, minimumColumnWidth),
                                readOnly: cell?.readOnly ? cell?.readOnly : false,
                                inputType: cell?.inputType ?? undefined,
                                contextDisable: cell.contextDisable,
                            };
                        }
                    });
                });
                const readOnlyCells = new Set([
                    ...(sheet?.rows?.readOnly
                        ? sheet.rows.readOnly.map((r) => `r${r}`)
                        : []),
                    ...(sheet?.columns?.readOnly
                        ? sheet.columns.readOnly.map((c) => `c${c}`)
                        : []),
                    ...(sheet?.cells?.readOnly
                        ? sheet.cells.readOnly.map(([r, c]) => `${r},${c}`)
                        : []),
                ]);
                const getInputTypeForCell = (rowIndex, colIndex, cell) => {
                    if (cell?.inputType) {
                        return cell.inputType;
                    }
                    const inputTypeConfig = sheet?.rows?.inputType?.[rowIndex + 1] ||
                        sheet?.columns?.inputType?.[colIndex + 1] ||
                        sheet?.cells?.inputType?.[`${rowIndex + 1},${colIndex + 1}`];
                    return inputTypeConfig || { type: 'text' };
                };
                spreadsheetData.forEach((row, rowIndex) => {
                    row.forEach((cell, colIndex) => {
                        if (!spreadsheetData[rowIndex]) {
                            spreadsheetData[rowIndex] = [];
                        }
                        const isReadOnly = readOnlyCells.has(`r${rowIndex + 1}`) ||
                            readOnlyCells.has(`c${colIndex + 1}`) ||
                            readOnlyCells.has(`${rowIndex + 1},${colIndex + 1}`);
                        const inputType = getInputTypeForCell(rowIndex, colIndex, cell || EmptyCell);
                        spreadsheetData[rowIndex][colIndex] = {
                            ...cell,
                            value: cell?.value ?? '',
                            readOnly: cell?.readOnly ? cell.readOnly : isReadOnly,
                            inputType: inputType,
                            contextDisable: cell?.contextDisable,
                        };
                    });
                });
                newWorksheetsData[sheetName] = spreadsheetData;
                // Only set headerOldNew if onSave expects two arguments
                if (onSave.length > 1) {
                    const firstRow = json[0] || [];
                    newHeaderOldNew[sheetName] = Array.from({ length: maxCols }, (_, col) => ({
                        newData: '',
                        oldData: firstRow[col]?.value || '',
                    }));
                }
            });
            setWorksheetsData(newWorksheetsData);
            if (onSave.length > 1) {
                setHeaderOldNew(newHeaderOldNew);
            }
            const firstSheetName = Object.keys(newWorksheetsData)[0];
            if (firstSheetName && newWorksheetsData[firstSheetName] !== undefined) {
                setSelectedSheetData(newWorksheetsData[firstSheetName]);
            }
        }
    }, [excelData]);
    useEffect(() => {
        if (onSaveInfoChange) {
            onSaveInfoChange(saveInfo);
        }
        if (saveInfo === 'File saved') {
            setTimeout(() => {
                setSaveInfo('');
            }, 2000);
        }
    }, [saveInfo]);
    useEffect(() => {
        setSaveInfo('Saving...');
        debounceDispatch(handleSaveData());
    }, [worksheetsData, pageRef.current]);
    const debounceDispatch = React.useCallback(debounce((val) => {
        if (onSave.length > 1) {
            const updatedHeader = { ...headerOldNew };
            sheetNames.forEach((sheetName, index) => {
                const firstRow = val[index].data[0] || [];
                const currentHeaders = firstRow.map((cell) => cell?.value || '');
                updatedHeader[sheetName] = (updatedHeader[sheetName] || []).map((h, i) => ({
                    ...h,
                    newData: currentHeaders[i] || '',
                }));
            });
            setHeaderOldNew(updatedHeader);
            const headerOldNewData = sheetNames.map((sheetName) => ({
                sheetName,
                headers: updatedHeader[sheetName] || [],
            }));
            onSave(val, headerOldNewData);
        }
        else {
            onSave(val);
        }
        setSaveInfo('File saved');
    }, onSaveDelay), [onSave, headerOldNew, sheetNames]);
    const handleSave = React.useCallback((event) => {
        if (event.ctrlKey && event.key === 's') {
            event.preventDefault();
            event.stopPropagation();
            debounceDispatch(handleSaveData());
        }
    }, [onSave]);
    React.useEffect(() => {
        document.addEventListener('keydown', handleSave);
        return () => {
            document.removeEventListener('keydown', handleSave);
        };
    }, [handleSave]);
    const handleSaveData = () => {
        return sheetNames.map((sheetName) => {
            const sheetData = worksheetsData[sheetName]?.map((row) => {
                const lastIndex = row.reduce((lastIdx, cell, i) => {
                    const value = cell?.value ?? '';
                    const hasValue = String(value).trim() !== '';
                    return hasValue ? i : lastIdx;
                }, -1);
                const filteredRow = row
                    .map((cell, index) => {
                    if (cell && cell.style && index <= lastIndex) {
                        return {
                            value: cell.value,
                            style: convertStyleToBackend(cell.style, minimumColumnWidth),
                            readOnly: cell.readOnly,
                            inputType: cell.inputType,
                            contextDisable: cell.contextDisable,
                        };
                    }
                    return null;
                })
                    .filter((cell) => cell !== null);
                return filteredRow.length > 0 ? filteredRow : [];
            }) || [];
            const finalData = sheetData.filter((row, index) => {
                const isNextRowNotEmpty = sheetData
                    .slice(index + 1)
                    .some((nextRow) => nextRow.length > 0);
                return row.length > 0 || isNextRowNotEmpty;
            });
            return {
                sheetName: sheetName,
                data: checkEmpty(finalData.length) ? [[]] : finalData,
            };
        });
    };
    const onEvaluateChange = (data) => {
        setWorksheetsData((prev) => ({ ...prev, [pageRef.current]: data }));
    };
    const [editingSheet, setEditingSheet] = useState(null);
    const addSheetIconDisable = () => sheetNames.length >= maxSheetLimit;
    const handleAddSheet = () => {
        if (addSheetIconDisable())
            return;
        const generateUniqueSheetName = (baseName, existingNames) => {
            const lowerExisting = existingNames.map((n) => n.toLowerCase());
            let newName = `${baseName}1`;
            let counter = 2;
            while (lowerExisting.includes(newName.toLowerCase())) {
                newName = `${baseName}${counter}`;
                counter++;
            }
            return newName;
        };
        const baseName = 'Sheet';
        const existingSheetNames = sheetNames;
        const newSheetName = generateUniqueSheetName(baseName, existingSheetNames);
        const newSheetData = Array.from({ length: rowCount }, () => Array.from({ length: colCount }, () => EmptyCell));
        setSheetNames((prev) => [...prev, newSheetName]);
        setSelectedSheet({ index: sheetNames?.length, name: newSheetName });
        setWorksheetsData({ ...worksheetsData, [newSheetName]: newSheetData });
        setSelectedSheetData(newSheetData);
        if (onSave.length > 1) {
            setHeaderOldNew((prev) => ({
                ...prev,
                [newSheetName]: Array.from({ length: colCount }, () => ({
                    newData: '',
                    oldData: '',
                })),
            }));
        }
        pageRef.current = newSheetName;
    };
    const handleToSetSelectedSheetData = (selectedData = [[EmptyCell]]) => {
        setSelectedSheetData(selectedData);
    };
    const handleDeleteSheet = (name, index) => {
        if (sheetNames.length > 1) {
            let updatedSheetNames = sheetNames.slice();
            updatedSheetNames.splice(index, 1);
            const updatedWorksheetsData = { ...worksheetsData };
            delete updatedWorksheetsData[name];
            const newIndex = Math.min(index, updatedSheetNames.length - 1);
            setSheetNames(updatedSheetNames);
            setWorksheetsData(updatedWorksheetsData);
            if (onSave.length > 1) {
                setHeaderOldNew((prev) => {
                    const newPrev = { ...prev };
                    delete newPrev[name];
                    return newPrev;
                });
            }
            const sheetName = updatedSheetNames[newIndex]
                ? updatedSheetNames[newIndex]
                : '';
            setSelectedSheet({
                index: newIndex,
                name: sheetName,
            });
            handleToSetSelectedSheetData(updatedWorksheetsData?.[sheetName]);
            pageRef.current = sheetName;
        }
        else {
            toast.warning('Cannot delete the last sheet.');
        }
    };
    const handleNameChange = (event, index, name) => {
        const target = event.target;
        if (!target || target?.textContent?.trim() === name?.trim()) {
            setEditingSheet(null);
            return;
        }
        const updatedSheetValue = (target.textContent || '').trim();
        if (!updatedSheetValue) {
            toast.warning('Sheet name cannot be empty.');
            target.textContent = selectedSheet.name;
            setEditingSheet(null);
            return;
        }
        if (updatedSheetValue.length > 50) {
            toast.warning('The sheet name cannot be greater than 50 characters');
            target.textContent = selectedSheet.name;
            setEditingSheet(null);
            return;
        }
        if (sheetNames
            .map((name) => name.toLowerCase())
            .includes(updatedSheetValue.toLowerCase()) &&
            name.trim()?.toLowerCase() !== updatedSheetValue?.toLowerCase()) {
            toast.warning('Sheet name already exists');
            target.textContent = selectedSheet.name;
            setEditingSheet(null);
            return;
        }
        let updatedSheetNames = sheetNames;
        handleToSetSelectedSheetData(worksheetsData?.[name]);
        updatedSheetNames.splice(index, 1, updatedSheetValue);
        let remainingSheets = worksheetsData;
        const updatedData = replaceKeyValueByKeyName(remainingSheets, name, updatedSheetValue);
        pageRef.current = updatedSheetValue;
        setSelectedSheet((prev) => ({ ...prev, name: updatedSheetValue }));
        setWorksheetsData(updatedData);
        if (onSave.length > 1) {
            setHeaderOldNew((prev) => {
                const newPrev = { ...prev };
                const headers = newPrev[name];
                delete newPrev[name];
                newPrev[updatedSheetValue] = headers ?? [];
                return newPrev;
            });
        }
        setEditingSheet(null);
    };
    function replaceKeyValueByKeyName(obj, oldKey, newKey) {
        if (!(oldKey in obj)) {
            throw new Error(`Key "${oldKey}" not found in object`);
        }
        const { [oldKey]: oldValue, ...rest } = obj;
        return {
            ...rest,
            [newKey]: oldValue ?? [],
        };
    }
    const handleSheetChange = (name, index) => {
        if (name === selectedSheet.name || index === selectedSheet.index) {
            return;
        }
        setSelectedSheet({ index, name });
        setSheetNames((prev) => {
            const updatedSheetNames = [...prev];
            updatedSheetNames[index] = name;
            return updatedSheetNames;
        });
        handleToSetSelectedSheetData(worksheetsData[name]);
        pageRef.current = name;
    };
    const setCursorToEnd = (element) => {
        const range = document.createRange();
        const selection = window.getSelection();
        range.selectNodeContents(element);
        range.collapse(false);
        selection?.removeAllRanges();
        selection?.addRange(range);
    };
    const handleClickOutside = React.useCallback((event, isLeftClick = false) => {
        const target = event.target;
        if (!(target.closest('.ff-excel-tab-list') ||
            target.closest('.ff-excel-sheet')) ||
            isLeftClick) {
            if (contextMenu.open) {
                setContextMenu({
                    open: false,
                    contextType: null,
                    options: [
                        {
                            label: '',
                            value: '',
                            iconName: '',
                            action: () => { },
                            disableTooltip: '',
                            visible: false,
                            disable: false,
                        },
                    ],
                });
                if (!isLeftClick) {
                    event.preventDefault();
                    event.stopPropagation();
                }
            }
        }
    }, [contextMenu.open]);
    React.useEffect(() => {
        document.addEventListener('contextmenu', handleClickOutside);
        document.addEventListener('click', (e) => handleClickOutside(e, true));
        return () => {
            document.removeEventListener('contextmenu', handleClickOutside);
            document.removeEventListener('click', (e) => handleClickOutside(e, true));
        };
    }, [handleClickOutside]);
    const contextClick = (event, name, index) => {
        event.preventDefault();
        const options = [
            {
                label: 'Add Sheet',
                value: 'Add Sheet',
                iconName: 'plus_icon',
                action: () => handleAddSheet(),
                disableTooltip: 'Sheet limit reached',
                visible: false,
                disable: addSheetIconDisable(),
            },
            ...(!disableDeleteOption
                ? [
                    {
                        label: 'Delete Sheet',
                        value: 'Delete Sheet',
                        iconName: 'delete',
                        action: () => handleDeleteSheet(name, index),
                        disableTooltip: '',
                        visible: false,
                        disable: false,
                    },
                ]
                : []),
        ];
        setContextMenu((prev) => ({
            ...prev,
            open: true,
            contextType: 'sheet',
            options,
        }));
    };
    const setContextPosition = (event) => {
        event.preventDefault();
        const rect = sheetRef.current?.parentElement?.getBoundingClientRect();
        const xOffset = window.scrollX;
        const yOffset = window.scrollY;
        let sheetRefX = event.clientX - (rect?.left || 0) + xOffset;
        let sheetRefY = event.clientY - (rect?.top || 0) + yOffset;
        const menuWidth = 300;
        const menuHeight = 200;
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;
        const spaceOnRight = windowWidth - event.clientX;
        const spaceOnLeft = event.clientX;
        const spaceBelow = windowHeight - event.clientY;
        const spaceAbove = event.clientY;
        // Horizontal positioning: left if no space on right
        if (spaceOnRight < menuWidth && spaceOnLeft >= menuWidth) {
            sheetRefX = event.clientX - (rect?.left || 0) + xOffset - 150;
        }
        else {
            sheetRefX += 2;
        }
        // Vertical positioning: above if no space below
        if (spaceBelow < menuHeight && spaceAbove >= menuHeight) {
            sheetRefY = event.clientY - (rect?.top || 0) + yOffset - 20;
        }
        else {
            sheetRefY += 2;
        }
        if (event.target.classList.contains('ff-excel-tab-list')) {
            setPosition({
                x: sheetRefX,
                y: sheetRefY - (disableDeleteOption ? 32 : 65),
            });
            return;
        }
        // Ensure menu stays within window bounds
        if (sheetRefX + menuWidth > windowWidth) {
            sheetRefX = windowWidth - menuWidth - 2;
        }
        if (sheetRefX < 0) {
            sheetRefX = 2; // Prevent clipping off left edge
        }
        setPosition({
            x: sheetRefX + contextWidthPositioning,
            y: sheetRefY + contextHeightPositioning,
        });
    };
    const unsetContextPosition = (e) => {
        e.stopPropagation();
        if (contextMenu.open) {
            setContextMenu({
                open: false,
                contextType: null,
                options: [
                    {
                        label: '',
                        value: '',
                        iconName: '',
                        action: () => { },
                        disableTooltip: '',
                        visible: false,
                        disable: false,
                    },
                ],
            });
        }
    };
    const handleAddColumn = (column, isLeft) => {
        if (onSave.length > 1) {
            setHeaderOldNew((prev) => {
                const sheetName = selectedSheet.name;
                const arr = [...(prev[sheetName] || [])];
                const pos = isLeft ? column : column + 1;
                arr.splice(pos, 0, { newData: '', oldData: '' });
                return { ...prev, [sheetName]: arr };
            });
        }
    };
    const handleDeleteColumn = (column) => {
        if (onSave.length > 1) {
            setHeaderOldNew((prev) => {
                const sheetName = selectedSheet.name;
                const arr = [...(prev[sheetName] || [])];
                arr.splice(column, 1);
                return { ...prev, [sheetName]: arr };
            });
        }
    };
    useEffect(() => {
        spreadsheetRef.current?.removeSelect();
    }, [selectedSheet.name]);
    const options = (sheetNames) => {
        return sheetNames.map((sheetName, index) => {
            const isMatchWithSheet = selectedSheet?.name === sheetName;
            return {
                label: (_jsxs("div", { style: { display: 'flex', gap: '8px' }, children: [isMatchWithSheet ? (_jsx(Icon, { height: 16, width: 16, name: "tick" })) : (_jsx("div", { style: { height: '16px', width: '24px' } })), _jsx(Tooltip, { title: isTextTruncated(sheetName, 20, 'count') ? sheetName : '', children: _jsx(Typography, { children: truncateText(sheetName, 20, 'count') }) })] })),
                name: index,
                value: sheetName,
            };
        });
    };
    const handleOptionClick = (option) => {
        const { value, name: index = '' } = option;
        handleSheetChange(value, parseInt(index));
    };
    return (_jsx(_Fragment, { children: sheetNames.length > 0 && (_jsxs("div", { ref: workRef, className: "ff-excel", onContextMenu: setContextPosition, onClick: unsetContextPosition, children: [_jsx("div", { ref: sheetRef, className: "ff-excel-sheet", children: _jsx(Spreadsheet, { ref: spreadsheetRef, editable: editable, attachmentAction: attachmentAction, toolbar: toolbar, sheetHeight: sheetHeight, setContextMenu: setContextMenu, contextOption: contextOption, data: selectedSheetData, columnContextEnable: columnContextEnable, rowContextEnable: rowContextEnable, minimumColumnWidth: minimumColumnWidth, onEvaluatedDataChange: onEvaluateChange, workRef: workRef, scroller: scroller, maxRowLimit: maxRowLimit, maxColLimit: maxColLimit, disableDeleteOption: disableDeleteOption, contextMenu: contextMenu, getActiveCell: getActiveCell, onAddColumn: handleAddColumn, onDeleteColumn: handleDeleteColumn }, selectedSheet.name) }), sheetBar !== 'hide' && (_jsxs("div", { className: "ff-excel-sheet-bar", children: [sheetBar === 'show' && (_jsxs("div", { className: "ff-excel-add-sheet-set", children: [_jsx(Tooltip, { title: addSheetIconDisable()
                                        ? 'Sheet limit reached'
                                        : 'Add Sheet', placement: "top", children: _jsx(Icon, { disabled: !editable || addSheetIconDisable(), className: "ff-excel-add-sheet-icon", hoverEffect: true, onClick: handleAddSheet, name: "plus_icon", height: 20, width: 20 }) }), _jsx(MenuOption, { options: options(sheetNames), targetRef: menuRef, onOptionClick: handleOptionClick, dropdownPlacement: "top", iconName: "show_script", tooltipTitle: "All Sheets", tooltipPlacement: "top", dropdownHeight: 215, selectedValue: selectedSheet.name })] })), _jsx("div", { className: "ff-excel-tab-container", children: sheetNames.map((name, index) => (_jsx(Typography, { lineHeight: "16px", children: _jsx("div", { onContextMenu: (event) => {
                                        handleSheetChange(name, index);
                                        if (sheetBarContextEnable) {
                                            contextClick(event, name, index);
                                        }
                                    }, className: classNames('ff-excel-tab-list', {
                                        active: name === selectedSheet.name,
                                    }), onClick: () => {
                                        handleSheetChange(name, index);
                                    }, suppressContentEditableWarning: editingSheet === index, onDoubleClick: (e) => {
                                        if (sheetBar === 'show') {
                                            setEditingSheet(index);
                                            if (editingSheet === null) {
                                                setTimeout(() => setCursorToEnd(e.target), 0);
                                            }
                                        }
                                    }, contentEditable: editable && editingSheet === index, onBlur: (e) => {
                                        handleNameChange(e, index, name);
                                    }, onKeyDown: (e) => {
                                        if (e.key === 'Enter') {
                                            e.preventDefault();
                                            handleNameChange(e, index, name);
                                        }
                                    }, children: name }) }, name))) })] })), contextMenu.open && (_jsx(ExcelContextMenu, { contextMenu: contextMenu, position: position, editable: editable })), _jsx(Toastify, {})] })) }));
};
export default ExcelFile;
//# sourceMappingURL=ExcelFile.js.map