import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import classnames from 'classnames';
import * as Actions from './actions';
import useSelector from './use-selector';
import useDispatch from './use-dispatch';
import { getCellDimensions, getOffsetRect, getSelectedDimensions, } from './util';
import * as Matrix from './matrix';
import Select from '../../../Select';
import AttachmentButton from '../../../AttachmentButton';
import { toast } from '../../../Toastify/Toastify';
import EditableCell from './EditableCell';
const ActiveCell = (props) => {
    const rootRef = React.useRef(null);
    const selectRef = React.useRef(null);
    const dispatch = useDispatch();
    const setCellData = React.useCallback((active, data) => dispatch(Actions.setCellData(active, data)), [dispatch]);
    const activate = React.useCallback((point) => dispatch(Actions.activate(point)), [dispatch]);
    const edit = React.useCallback(() => dispatch(Actions.edit()), [dispatch]);
    const autoFill = React.useCallback((value) => dispatch(Actions.autoFill(value)), [dispatch]);
    const commit = React.useCallback((changes) => dispatch(Actions.commit(changes)), [dispatch]);
    const view = React.useCallback(() => {
        dispatch(Actions.view());
    }, [dispatch]);
    const rowDimensions = useSelector((state) => state.rowDimensions);
    const active = useSelector((state) => state.active);
    const mode = useSelector((state) => state.mode);
    const cell = useSelector((state) => state.active ? Matrix.get(state.active, state.model.data) : undefined);
    const selected = useSelector((state) => state.selected);
    const selectedDimensions = useSelector((state) => {
        return (selected &&
            getSelectedDimensions(state.rowDimensions, state.columnDimensions, state.model.data, state.selected));
    });
    const dimensions = useSelector((state) => {
        let dimensionValue = active
            ? getCellDimensions(active, state.rowDimensions, state.columnDimensions)
            : undefined;
        dimensionValue = {
            top: dimensionValue?.top ? dimensionValue?.top : 0,
            height: dimensionValue?.height ? dimensionValue?.height : 0,
            left: dimensionValue?.left ? dimensionValue?.left : 0,
            width: dimensionValue?.width ? dimensionValue?.width : 0,
        };
        return dimensionValue;
    });
    const hidden = React.useMemo(() => !active ||
        !dimensions ||
        active.row < props.visibleRowRange.start ||
        active.row >= props.visibleRowRange.end ||
        active.column < props.visibleColRange.start ||
        active.column >= props.visibleColRange.end, [active, dimensions, props.visibleRowRange, props.visibleColRange]);
    const initialCellRef = React.useRef(undefined);
    const prevActiveRef = React.useRef(null);
    const prevCellRef = React.useRef(undefined);
    const handleChange = React.useCallback((cell) => {
        if (!active) {
            return;
        }
        setCellData(active, cell);
    }, [setCellData, active]);
    const [dropDownValue, setDropDownValue] = React.useState({
        value: '',
        name: '',
    });
    const [selectOption, setSelectOption] = React.useState(false);
    const [allOption, setAllOption] = React.useState();
    const [selectedFiles, setSelectedFiles] = React.useState([]);
    const handleFilesChange = async (newFiles, selected, actionType) => {
        try {
            if (actionType === 'ADD' && cell?.inputType?.type === 'file') {
                // Parse existing cell.value
                let existingFiles = [];
                try {
                    if (cell?.value) {
                        existingFiles = JSON.parse(cell.value);
                    }
                }
                catch (error) {
                    console.error('Error parsing cell.value:', error);
                }
                // Deduplicate within newFiles and against existingFiles
                let duplicateCount = 0;
                const uniqueFiles = newFiles.filter((file, index, self) => {
                    const baseName = file.name.split('*')[0];
                    const isDuplicateInSelf = self.findIndex((f) => f.name.split('*')[0] === baseName) !== index;
                    const isDuplicateInExisting = existingFiles.some((existingFile) => existingFile.name.split('*')[0] === baseName);
                    if (isDuplicateInSelf || isDuplicateInExisting) {
                        duplicateCount++;
                        return false;
                    }
                    return true;
                });
                // Check total file count
                if (existingFiles.length + uniqueFiles.length > 5) {
                    toast.info('Cannot upload more than 5 files.');
                    return;
                }
                if (props.attachmentAction?.addAttachment && uniqueFiles.length > 0) {
                    try {
                        let successCount = 0;
                        let failureCount = 0;
                        let memoryFullCount = 0;
                        const fileLength = selectedFiles?.length + uniqueFiles?.length;
                        const extractHeight = fileLength > 0 ? fileLength * 25 : 1;
                        const processedFiles = [...existingFiles];
                        const uploadPromises = uniqueFiles?.map(async (file) => {
                            try {
                                if (file.name.includes('*')) {
                                    return {
                                        file,
                                        status: 'existing',
                                        data: { name: file.name },
                                    };
                                }
                                const response = await props?.attachmentAction?.addAttachment(file);
                                if (!response ||
                                    (typeof response === 'string' && response.trim().length === 0)) {
                                    return { file, status: 'failed', reason: 'no response' };
                                }
                                if (typeof response === 'string') {
                                    try {
                                        const parsedResponse = JSON.parse(response);
                                        if (parsedResponse.responseCode === 507) {
                                            return {
                                                file,
                                                status: 'memory_full',
                                                reason: 'no memory',
                                            };
                                        }
                                        if (parsedResponse.responseCode === 400) {
                                            return { file, status: 'failed', reason: 'invalid file' };
                                        }
                                        if (parsedResponse?.id && parsedResponse?.name) {
                                            return { file, status: 'success', data: parsedResponse };
                                        }
                                        else {
                                            console.error(`Invalid response structure for ${file.name}:`, parsedResponse);
                                            return {
                                                file,
                                                status: 'failed',
                                                reason: 'invalid response',
                                            };
                                        }
                                    }
                                    catch (error) {
                                        console.error(`Parse error for ${file.name}:`, error);
                                        return { file, status: 'failed', reason: 'parse error' };
                                    }
                                }
                                if (typeof response === 'object' && response !== null) {
                                    const typedResponse = response;
                                    if (typedResponse?.id && typedResponse?.name) {
                                        return { file, status: 'success', data: typedResponse };
                                    }
                                    else {
                                        console.error(`Invalid response structure for ${file.name}:`, response);
                                        return {
                                            file,
                                            status: 'failed',
                                            reason: 'invalid response',
                                        };
                                    }
                                }
                                console.error(`Unknown response for ${file.name}:`, response);
                                return { file, status: 'failed', reason: 'unknown' };
                            }
                            catch (error) {
                                console.error(`Upload failed for ${file.name}:`, error);
                                return { file, status: 'failed', reason: 'upload error' };
                            }
                        });
                        const results = await Promise.allSettled(uploadPromises);
                        results.forEach((result) => {
                            if (result.status === 'fulfilled' && result.value) {
                                const { status, data } = result.value;
                                if (status === 'success' && data?.id && data?.name) {
                                    processedFiles.push(data);
                                    successCount++;
                                }
                                else if (status === 'existing' && data?.name) {
                                    processedFiles.push(data);
                                }
                                else if (status === 'memory_full') {
                                    memoryFullCount++;
                                }
                                else {
                                    failureCount++;
                                }
                            }
                            else {
                                failureCount++;
                            }
                        });
                        if (successCount > 0 ||
                            processedFiles.length > existingFiles.length) {
                            const newValue = processedFiles.length > 0 ? JSON.stringify(processedFiles) : '';
                            handleChange({
                                ...cell,
                                value: newValue,
                                style: cell?.style,
                                inputType: cell?.inputType,
                            });
                            dispatch(Actions.setRowHeight(active?.row || 0, Math.max(extractHeight, rowDimensions?.[active.row]?.height || extractHeight)));
                            setSelectedFiles(processedFiles.map((file) => new File([new Blob()], file.name?.split('*')[0] ?? 'default')));
                        }
                        if (memoryFullCount > 0) {
                            toast.info('No memory available to add the file');
                        }
                        if (successCount > 0) {
                            toast.success(`${successCount} file${successCount > 1 ? 's' : ''} uploaded successfully`);
                        }
                        if (failureCount > 0) {
                            toast.info(`${failureCount} unsupported ${failureCount > 1 ? 'files' : 'file'}. Please check the file formats.`);
                        }
                    }
                    catch (error) {
                        console.error('Upload operation failed:', error);
                        toast.error('Operation failed');
                    }
                }
            }
            else if (actionType === 'DELETE' && cell?.inputType?.type === 'file') {
                try {
                    const parsedValue = cell && JSON.parse(cell.value);
                    let updatedFileDetails = [...parsedValue];
                    let deletedCount = 0;
                    for (const file of selected || []) {
                        const index = updatedFileDetails.findIndex((originalFile) => originalFile.name.split('*')[0] === file.name.split('*')[0]);
                        const fileId = updatedFileDetails[index]?.id;
                        if (index !== -1 &&
                            fileId &&
                            props.attachmentAction?.deleteAttachment) {
                            try {
                                const response = await props.attachmentAction.deleteAttachment(fileId);
                                // Check for valid response
                                if (response === 'SUCCESS' ||
                                    (typeof response === 'object' &&
                                        response !== null &&
                                        (('status' in response &&
                                            response.status === 'SUCCESS') ||
                                            ('responseCode' in response &&
                                                response.responseCode === 200)))) {
                                    updatedFileDetails.splice(index, 1);
                                    deletedCount++;
                                }
                                else {
                                    console.error(`Delete failed for ${file.name}: Invalid response`, response);
                                }
                            }
                            catch (deleteError) {
                                console.error(`Delete error for ${file.name}:`, deleteError);
                                toast.error('Error deleting file');
                            }
                        }
                        else {
                            console.error(`Cannot delete ${file.name}: Invalid fileId or no match`, {
                                index,
                                fileId,
                                hasDeleteAttachment: !!props.attachmentAction?.deleteAttachment,
                            }); // Debug log
                            toast.error('Failed to delete file: Invalid file data');
                        }
                    }
                    // Update cell value and selected files
                    if (deletedCount > 0) {
                        const newValue = updatedFileDetails.length > 0
                            ? JSON.stringify(updatedFileDetails)
                            : '';
                        handleChange({
                            ...cell,
                            value: newValue,
                            style: cell?.style,
                            inputType: cell?.inputType,
                        });
                        setSelectedFiles(updatedFileDetails?.map((file) => new File([new Blob()], file.name.split('*')[0])));
                        toast.success(`${deletedCount} file${deletedCount > 1 ? 's' : ''} deleted successfully`);
                    }
                    else if (selected?.length) {
                        const validFiles = updatedFileDetails?.filter((file) => file.id && file.name);
                        if (validFiles.length < updatedFileDetails.length) {
                            const newValue = validFiles.length > 0 ? JSON.stringify(validFiles) : '';
                            handleChange({
                                ...cell,
                                value: newValue,
                                style: cell?.style,
                                inputType: cell?.inputType,
                            });
                            setSelectedFiles(validFiles.map((file) => new File([new Blob()], file.name.split('*')[0])));
                            toast.error('Failed to delete file(s). Invalid file data detected.');
                        }
                        else {
                            toast.error('Failed to delete file(s). No valid files removed.');
                        }
                    }
                }
                catch (error) {
                    console.error('Delete operation failed:', error);
                    toast.error('Delete operation failed');
                }
            }
        }
        catch (error) {
            console.error('handleFilesChange error:', error);
            toast.error('Operation failed');
        }
    };
    const handleClick = (e) => {
        const fileElement = e.target.closest('.ff-attachment-files');
        const isIconClick = e.target.closest('.ff-icon-container, .ff-icon-click, .ff-icon-danger');
        if (!fileElement ||
            isIconClick ||
            !cell?.value ||
            !props.attachmentAction?.viewAttachment) {
            console.warn('Missing file element, icon click, cell value, or viewAttachment action');
            return;
        }
        try {
            const files = JSON.parse(cell.value);
            const fileElements = fileElement.parentElement?.querySelectorAll('.ff-attachment-files') ||
                [];
            const fileIndex = Array.from(fileElements).indexOf(fileElement);
            if (fileIndex === -1 || !files[fileIndex]) {
                console.error('File index not found or invalid');
                return;
            }
            const file = files[fileIndex];
            props.attachmentAction.viewAttachment(file.id, file.name?.split('*')[0] ?? 'default');
        }
        catch (error) {
            console.error('Error parsing cell value:', error);
        }
    };
    React.useEffect(() => {
        if (cell && active) {
            props.getActiveCell({ value: cell.value, active: active });
        }
        const root = rootRef.current;
        if (!hidden && root) {
            root.focus({ preventScroll: true });
            if (cell?.inputType?.type === 'dropDown') {
                setDropDownValue({ value: cell?.value, name: cell?.value });
                setSelectOption((prev) => !prev);
                const getAllOption = cell?.inputType?.options?.map((option) => ({
                    disable: option.disable,
                    label: _jsx("span", { style: { color: option.color }, children: option.label }),
                    value: option.value,
                }));
                setAllOption(getAllOption);
            }
        }
    }, [
        //Do not add extra dependencies it will cause auto save and auto focussing out issue
        rootRef,
        hidden,
        active?.row,
        active?.column,
    ]);
    React.useEffect(() => {
        if (cell?.inputType?.type === 'file' && cell?.value) {
            try {
                const parsedFiles = JSON.parse(cell.value).map((file) => new File([new Blob()], file.name.split('*')[0] ?? 'default'));
                setSelectedFiles(parsedFiles);
            }
            catch (error) {
                console.error('Error parsing cell value for files:', error);
                setSelectedFiles([]);
            }
        }
        else {
            setSelectedFiles([]);
        }
    }, [cell?.inputType?.type, cell?.value]);
    React.useEffect(() => {
        if (cell?.inputType?.type === 'dropDown' &&
            cell?.value !== dropDownValue.value) {
            setDropDownValue({ value: cell?.value, name: cell?.value });
        }
    }, [cell?.value, cell?.inputType?.type, dropDownValue.value]);
    React.useEffect(() => {
        const prevActive = prevActiveRef.current;
        const prevCell = prevCellRef.current;
        prevActiveRef.current = active;
        prevCellRef.current = cell;
        if (!prevActive || !prevCell) {
            return;
        }
        const coordsChanged = active?.row !== prevActive.row || active?.column !== prevActive.column;
        const exitedEditMode = mode !== 'edit';
        if (coordsChanged || exitedEditMode) {
            const initialCell = initialCellRef.current;
            if (prevCell !== initialCell) {
                commit([
                    {
                        prevCell: initialCell || null,
                        nextCell: prevCell,
                    },
                ]);
            }
            else if (!coordsChanged && cell !== prevCell) {
                commit([
                    {
                        prevCell,
                        nextCell: cell || null,
                    },
                ]);
            }
            initialCellRef.current = cell;
        }
    });
    const DataEditor = (cell && cell.DataEditor) || props.DataEditor;
    const readOnly = cell && cell.readOnly;
    const handleMouseDown = React.useCallback((e) => {
        if (!active)
            return;
        const spreadsheetContainer = e.currentTarget.closest('.ff-excel-spreadsheet');
        if (!spreadsheetContainer) {
            e.preventDefault();
            return;
        }
        e.stopPropagation();
        // 1. Capture original styles
        const originalUserSelect = document.body.style.userSelect;
        const originalOverflow = document.body.style.overflow;
        // 2. Apply "Dragging" mode
        document.body.style.userSelect = 'none';
        document.body.style.overflow = 'hidden';
        let autoScrollId = null;
        const startAutoScroll = (direction) => {
            stopAutoScroll(); // Clear previous
            const scroll = () => {
                const { x, y } = direction;
                if (x !== 0)
                    spreadsheetContainer.scrollLeft += x;
                if (y !== 0)
                    spreadsheetContainer.scrollTop += y;
                autoScrollId = requestAnimationFrame(scroll);
            };
            autoScrollId = requestAnimationFrame(scroll);
        };
        const stopAutoScroll = () => {
            if (autoScrollId) {
                cancelAnimationFrame(autoScrollId);
                autoScrollId = null;
            }
        };
        const handleMouseMove = (moveEvent) => {
            const rect = spreadsheetContainer.getBoundingClientRect();
            const threshold = 50;
            const speed = 12;
            let dx = 0;
            let dy = 0;
            // Vertical Calculation
            if (moveEvent.clientY < rect.top + threshold)
                dy = -speed;
            else if (moveEvent.clientY > rect.bottom - threshold)
                dy = speed;
            // Horizontal Calculation
            if (moveEvent.clientX < rect.left + threshold)
                dx = -speed;
            else if (moveEvent.clientX > rect.right - threshold)
                dx = speed;
            if (dx !== 0 || dy !== 0) {
                startAutoScroll({ x: dx, y: dy });
            }
            else {
                stopAutoScroll();
            }
        };
        const cleanup = () => {
            stopAutoScroll();
            document.body.style.userSelect = originalUserSelect;
            document.body.style.overflow = originalOverflow;
            document.removeEventListener('mousemove', handleMouseMove);
            document.removeEventListener('mouseup', cleanup);
        };
        document.addEventListener('mousemove', handleMouseMove);
        document.addEventListener('mouseup', cleanup);
        autoFill(true);
        // activate(active); need this line for future reference
    }, [activate, autoFill, active]);
    const contextClick = React.useCallback((event) => {
        event.preventDefault();
        props.setContextMenu({
            open: props.contextOption?.open ?? false,
            contextType: props.contextOption?.contextType ?? null,
            options: props.contextOption?.options || [],
        });
    }, [props]);
    const isDragged = selectedDimensions?.height !== dimensions?.height ||
        selectedDimensions?.width !== dimensions?.width;
    const handleCellClick = React.useCallback((event) => {
        if (active && isDragged) {
            Actions.setCellDimensions(active, getOffsetRect(event.currentTarget));
            activate(active);
        }
    }, [active, isDragged]);
    const availableWidth = props.isAtRight
        ? props.maxWidth - (dimensions?.left - props.scrollPos.left) + 100
        : props.maxWidth;
    const availableHeight = props.isAtBottom
        ? props.maxHeight - (dimensions?.top - props.scrollPos.top) + 64
        : props.maxHeight;
    const isFileOrDropDown = ['file', 'dropDown'].includes(cell?.inputType?.type || '');
    return (_jsxs("div", { ref: rootRef, className: classnames('ff-spreadsheet-active-cell', `ff-spreadsheet-active-cell--${mode}`, {
            'ff-spreadsheet-active-cell--hidden': hidden,
            'ff-spreadsheet-active-cell--dragging': isDragged && cell?.inputType?.type !== 'text',
        }), onMouseDown: handleCellClick, style: {
            ...dimensions,
            backgroundColor: cell?.style?.backgroundColor,
            ...(isFileOrDropDown
                ? {
                    display: 'flex',
                    alignItems: cell?.style?.alignContent,
                    justifyContent: cell?.style?.textAlign,
                }
                : {}),
            ...(mode === 'edit' && active
                ? {
                    minWidth: Math.min(dimensions?.width, props.maxWidth),
                    minHeight: Math.min(dimensions?.height, props.maxHeight),
                    height: 'auto',
                    maxWidth: `${availableWidth}px`,
                    maxHeight: `${availableHeight}px`,
                    overflow: 'auto',
                    ...(cell?.inputType?.type === 'dropDown'
                        ? {}
                        : { padding: '2px 4px 0px 4px', width: 'max-content' }),
                }
                : {}),
        }, onContextMenu: contextClick, onClick: mode === 'view' && !readOnly ? edit : undefined, tabIndex: 0, children: [_jsx("div", { className: isFileOrDropDown ? '' : 'active-cell-main', children: cell?.inputType?.type === 'dropDown' ? (_jsx(Select, { ...cell?.inputType?.inputProps, dropDownRef: selectRef, showOptions: {
                        open: mode === 'edit' && active ? true : false,
                        toggle: selectOption,
                    }, selectedOption: dropDownValue, optionsList: allOption || [], height: 26, showLabel: false, disabled: !props.editable, showBorder: false, optionZIndex: 5000, onChange: (value) => {
                        setDropDownValue({ value: value.value, name: value.label });
                        handleChange({
                            ...cell,
                            value: value.value,
                            style: cell?.style,
                            inputType: cell?.inputType,
                        });
                    } })) : cell?.inputType?.type === 'file' ? (_jsx(AttachmentButton, { ...cell?.inputType?.inputProps, label: "", onFileListClick: handleClick, selectedFiles: selectedFiles, onFilesChange: handleFilesChange, disabled: !props.editable, maxFiles: 5, buttonLabel: "+ Attachments", buttonVariant: "tertiary", deleteButton: props.editable, selectedFileMessage: "Duplicate attachments not allowed within the same row", addAttachmentButton: props.editable, isInfoIconRequired: false, truncateMaxLimit: (dimensions?.width ?? 0) - 60 })) : mode === 'edit' && active && props.editable ? (_jsx(DataEditor, { row: active.row, column: active.column, cell: cell, onChange: handleChange, exitEditMode: view })) : (_jsx(EditableCell, { initialValue: cell?.value, onChange: () => { }, className: "ff-spreadsheet-cell-textarea", style: {
                        ...cell?.style,
                        height: '100%',
                        width: '100%',
                        textDecoration: cell?.style?.textDecoration === 'underline'
                            ? 'underline'
                            : 'none',
                        backgroundColor: isDragged
                            ? '#1e161f00'
                            : cell?.style?.backgroundColor,
                        pointerEvents: 'none',
                        borderTop: '',
                        borderBottom: '',
                        borderLeft: '',
                        borderRight: '',
                    } })) }), !['file'].includes(cell?.inputType?.type ?? '') &&
                (mode === 'edit' ||
                    (active && (_jsx("div", { onMouseDown: handleMouseDown, className: "select_dot" }))))] }, `${active?.row}-${active?.column}`));
};
export default ActiveCell;
//# sourceMappingURL=ActiveCell.js.map