import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { ClientSideUdpGrid } from '../../../../../UI/templates/newGrid';
import { EmptyStateDisplay, LinearProgress, SideSheet } from '../../../../../UI';
import { FluentTextField } from '../../../../../UI/inputs/textField';
import { FluentButton } from '../../../../../UI/inputs/buttons';
import { LayoutUnit } from '../../../../../layout';
import { Typography } from '@material-ui/core';
import { apiMutate, useAxiosMutate } from '../../../../../utilities/useAxiosMutate';
import { ConfigService } from '../../../../../configService';
import { PDFViewer } from '../../../../../UI/fileViewer/pdfViewer';
import { useHandleAxiosSnackbar } from '../../../../../utilities';
import { ErrorIcon } from '@fluentui/react-icons';
const ALLOWED_EXTENSIONS = [
    'pdf',
    'jpg',
    'jpeg',
    'png',
    'gif',
    'bmp',
    'tif',
    'tiff'
];
export const TransactionAttachmentPdfStitcher = (props) => {
    const { transactionAttachments = [], onDownload, onPreview, onCancel, stitchLoading, orderedRows, onSelectionChanged, onRowOrderChanged, stitchedFileName, onFileNameChange, fileNameError, tableHeight = 'calc(100vh - 700px)', hidePreviewButton = false, hideDownloadButton = false, defaultPreviewSideSheet = true, transactionTypeId, transactionAttachmentTypes, disableFileName = false, onActionClick, actionButtonLabel = '', disableActionButton = false } = props;
    const { t } = useTranslation();
    const [orderedSelection, setOrderedSelection] = useState(orderedRows || []);
    const [sourceGridApi, setSourceGridApi] = useState(null);
    const [orderGridApi, setOrderGridApi] = useState(null);
    const [previewPdfOpen, setPreviewPdfOpen] = useState(false);
    const [previewPdfLoading, setPreviewPdfLoading] = useState(false);
    const [previewPdfError, setPreviewPdfError] = useState(null);
    const [previewPdfBlob, setPreviewPdfBlob] = useState(null);
    const [downloadingPdf, setDownloadingPdf] = useState(false);
    const { handleErrorSnackbar } = useHandleAxiosSnackbar();
    const [{ data: fetchedTransactionAttachmentTypes }, fetchTransactionAttachmentTypes] = useAxiosMutate(ConfigService.productV1ApiUrl, `UdpTransactionAttachmentType/search`, {
        method: 'post',
        data: {
            pageSize: 50,
            filterElements: [
                {
                    searchField: 'TransactionTypeId',
                    searchValue: transactionTypeId,
                    searchOperator: '='
                }
            ],
            getAll: true
        }
    });
    const resolvedTransactionAttachmentTypes = transactionAttachmentTypes !== null && transactionAttachmentTypes !== void 0 ? transactionAttachmentTypes : fetchedTransactionAttachmentTypes === null || fetchedTransactionAttachmentTypes === void 0 ? void 0 : fetchedTransactionAttachmentTypes.pageList;
    const executeGetStitchedPdf = useCallback(async () => {
        return await apiMutate(ConfigService.productV1ApiUrl, `UdpTransactionAttachment/stitchAttachmentsIntoPdf`, {
            method: 'POST',
            data: {
                fileName: stitchedFileName,
                transactionAttachments: orderedSelection
            },
            responseType: 'blob'
        }).catch(async (error) => {
            let errorMessage = '';
            if (error.response && error.response.data instanceof Blob) {
                // Convert the blob back to a string
                errorMessage = await error.response.data.text();
            }
            else {
                errorMessage = error.message;
            }
            handleErrorSnackbar(error, t(`Failed to generate PDF ${errorMessage ? `: ${errorMessage}` : ''}`));
            setPreviewPdfError(errorMessage);
        });
    }, [stitchedFileName, orderedSelection, handleErrorSnackbar, t]);
    const handleOnPreviewPdfClose = useCallback(() => {
        setPreviewPdfOpen(false);
        setPreviewPdfBlob(null);
        setPreviewPdfError(null);
    }, []);
    const handleRowOrderChanged = useCallback((newOrder) => {
        if (onRowOrderChanged) {
            onRowOrderChanged(newOrder);
        }
        if (onSelectionChanged) {
            onSelectionChanged(newOrder);
        }
        setOrderedSelection(newOrder);
    }, [onRowOrderChanged, onSelectionChanged]);
    const handleSelectionChanged = useCallback((selected) => {
        setOrderedSelection((prevOrdered) => {
            const selectedIds = new Set(selected.map((item) => item.transactionAttachmentId || item.id));
            // Filter previous order to keep only items that are still selected
            const nextOrdered = prevOrdered.filter((item) => selectedIds.has(item.transactionAttachmentId || item.id));
            const prevIds = new Set(prevOrdered.map((item) => item.transactionAttachmentId || item.id));
            const newItems = selected.filter((item) => !prevIds.has(item.transactionAttachmentId || item.id));
            const finalSelection = [...nextOrdered, ...newItems];
            if (onSelectionChanged) {
                onSelectionChanged(finalSelection);
            }
            return finalSelection;
        });
    }, [onSelectionChanged]);
    const filteredAttachments = useMemo(() => {
        return transactionAttachments.filter((item) => {
            const ext = item.extension
                ? item.extension.toLowerCase().replace('.', '')
                : '';
            return ALLOWED_EXTENSIONS.includes(ext);
        });
    }, [transactionAttachments]);
    const handleGridApiCallback = useCallback((api) => {
        setSourceGridApi(api);
    }, []);
    const handleOrderGridApiCallback = useCallback((api) => {
        setOrderGridApi(api);
    }, []);
    const getColumnDefs = useCallback((type) => {
        return [
            {
                field: 'fileName',
                headerName: t('File Name'),
                tooltipField: 'fileName',
                sortable: false,
                rowDrag: type === 'select' ? false : true
            },
            ...((transactionTypeId || transactionAttachmentTypes) &&
                type === 'select'
                ? [
                    {
                        headerName: t('Type'),
                        field: 'transactionAttachmentTypeId',
                        filter: 'agSetColumnFilter',
                        filterParams: {
                            values: (params) => {
                                const values = (resolvedTransactionAttachmentTypes === null || resolvedTransactionAttachmentTypes === void 0 ? void 0 : resolvedTransactionAttachmentTypes.map((taType) => taType.transactionAttachmentTypeId)) || [];
                                params.success(values);
                            },
                            valueFormatter: (params) => {
                                const type = resolvedTransactionAttachmentTypes === null || resolvedTransactionAttachmentTypes === void 0 ? void 0 : resolvedTransactionAttachmentTypes.find((taType) => taType.transactionAttachmentTypeId === params.value);
                                return type ? type.name : params.value;
                            }
                        },
                        valueFormatter: (params) => {
                            var _a;
                            const type = resolvedTransactionAttachmentTypes === null || resolvedTransactionAttachmentTypes === void 0 ? void 0 : resolvedTransactionAttachmentTypes.find((taType) => {
                                var _a;
                                return taType.transactionAttachmentTypeId ===
                                    ((_a = params === null || params === void 0 ? void 0 : params.data) === null || _a === void 0 ? void 0 : _a.transactionAttachmentTypeId);
                            });
                            return type
                                ? type.name
                                : (_a = params === null || params === void 0 ? void 0 : params.data) === null || _a === void 0 ? void 0 : _a.transactionAttachmentTypeId;
                        }
                    }
                ]
                : [])
        ];
    }, [
        t,
        resolvedTransactionAttachmentTypes,
        transactionTypeId,
        transactionAttachmentTypes
    ]);
    const selectAttachmentsGridOptions = useMemo(() => ({
        rowDragManaged: true,
        animateRows: true,
        suppressMoveWhenRowDragging: false,
        getRowId: (params) => {
            var _a, _b;
            return ((_a = params.data.transactionAttachmentId) === null || _a === void 0 ? void 0 : _a.toString()) ||
                ((_b = params.data.id) === null || _b === void 0 ? void 0 : _b.toString());
        },
        onSelectionChanged: (event) => {
            handleSelectionChanged(event.api.getSelectedRows());
        },
        rowSelection: {
            mode: 'multiRow'
        }
    }), [handleSelectionChanged]);
    const documentOrderGridOptions = useMemo(() => ({
        rowDragManaged: true,
        animateRows: true,
        suppressMoveWhenRowDragging: false,
        getRowId: (params) => {
            var _a, _b;
            return ((_a = params.data.transactionAttachmentId) === null || _a === void 0 ? void 0 : _a.toString()) ||
                ((_b = params.data.id) === null || _b === void 0 ? void 0 : _b.toString());
        },
        onRowDragEnd: (event) => {
            const newOrder = [];
            event.api.forEachNode((node) => {
                newOrder.push(node.data);
            });
            handleRowOrderChanged(newOrder); // This now calls setOrderedSelection
        },
        onSelectionChanged: (event) => {
            handleSelectionChanged(event.api.getSelectedRows());
        },
        headerHeight: 0
    }), [handleRowOrderChanged, handleSelectionChanged]);
    const handleDownload = useCallback(async () => {
        setDownloadingPdf(true);
        try {
            const response = onDownload
                ? await onDownload(orderedSelection)
                : await executeGetStitchedPdf();
            if (response) {
                const blob = response.data;
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `${stitchedFileName.trim().toLowerCase().endsWith('.pdf')
                    ? stitchedFileName
                    : `${stitchedFileName || 'merged_files'}.pdf`}`;
                a.click();
                URL.revokeObjectURL(url);
            }
        }
        finally {
            setDownloadingPdf(false);
        }
    }, [onDownload, orderedSelection, stitchedFileName, executeGetStitchedPdf]);
    const handlePreview = useCallback(async () => {
        // 1. Early return or simple execution if we aren't using the default UI
        if (onPreview && !defaultPreviewSideSheet) {
            return await onPreview(orderedSelection);
        }
        // 2. Setup UI state for the default SideSheet
        setPreviewPdfOpen(true);
        setPreviewPdfLoading(true);
        try {
            // 3. Determine which data source to use
            const request = onPreview
                ? onPreview(orderedSelection)
                : executeGetStitchedPdf();
            const response = await request;
            const blob = response === null || response === void 0 ? void 0 : response.data;
            if (blob instanceof Blob) {
                setPreviewPdfBlob(blob);
            }
        }
        finally {
            setPreviewPdfLoading(false);
        }
    }, [
        onPreview,
        orderedSelection,
        executeGetStitchedPdf,
        defaultPreviewSideSheet
    ]);
    useEffect(() => {
        if (!transactionAttachmentTypes && transactionTypeId) {
            fetchTransactionAttachmentTypes().catch(() => { });
        }
    }, [
        transactionAttachmentTypes,
        fetchTransactionAttachmentTypes,
        transactionTypeId
    ]);
    useEffect(() => {
        // Syncs the selection state of the top grid based on the orderedSelection state
        if (sourceGridApi) {
            const selectionIds = new Set(orderedSelection.map((item) => item.transactionAttachmentId || item.id));
            sourceGridApi.forEachNode((node) => {
                const isActuallySelected = selectionIds.has(node.data.transactionAttachmentId || node.data.id);
                if (node.isSelected() !== isActuallySelected) {
                    node.setSelected(isActuallySelected, false, true);
                }
            });
        }
    }, [sourceGridApi, orderedSelection]);
    return (React.createElement("div", { style: { height: '100%' } }, (stitchLoading || downloadingPdf) && React.createElement(LinearProgress, null), React.createElement("div", { style: { paddingBottom: 8 } }, React.createElement(FluentTextField, { label: t('File Name'), value: stitchedFileName, onChange: onFileNameChange, error: !!fileNameError, helperText: fileNameError, fullWidth: true, variant: "outlined", disabled: disableFileName })), React.createElement(Typography, null, t('Select Attachments (Optional)')), React.createElement(LayoutUnit, { unit: "nudge" }), React.createElement(ClientSideUdpGrid, { columnDefs: getColumnDefs('select'), rowData: filteredAttachments || [], gridOptions: selectAttachmentsGridOptions, gridApiCallback: handleGridApiCallback, gridHeight: tableHeight }), React.createElement(LayoutUnit, { unit: "nudge" }), React.createElement(Typography, null, t('Document Order')), React.createElement(LayoutUnit, { unit: "nudge" }), React.createElement(ClientSideUdpGrid, { columnDefs: getColumnDefs('order'), rowData: orderedSelection, gridOptions: documentOrderGridOptions, gridApiCallback: handleOrderGridApiCallback, gridHeight: tableHeight }), React.createElement("div", { style: {
            display: 'flex',
            justifyContent: 'flex-start',
            paddingTop: '8px'
        } }, hidePreviewButton ? null : (React.createElement(FluentButton, { color: "primary", disabled: !(orderedSelection === null || orderedSelection === void 0 ? void 0 : orderedSelection.length), onClick: handlePreview }, t('Preview'))), hideDownloadButton ? null : (React.createElement(FluentButton, { color: "primary", disabled: !(orderedSelection === null || orderedSelection === void 0 ? void 0 : orderedSelection.length) || downloadingPdf, onClick: handleDownload }, t('Download'))), onActionClick && (React.createElement(FluentButton, { color: "primary", disabled: disableActionButton, onClick: onActionClick }, t(actionButtonLabel || 'Perform Action')))), React.createElement(SideSheet, { open: previewPdfOpen, title: t('PDF Preview'), onClose: handleOnPreviewPdfClose, width: 660, progress: previewPdfLoading, variant: "indeterminate", color: "primary" }, previewPdfError ? (React.createElement(EmptyStateDisplay, { icon: ErrorIcon, primaryText: 'Error loading PDF preview', secondaryText: previewPdfError ||
            t('An error occurred while generating the PDF preview.') })) : (React.createElement(PDFViewer, { blobPDF: previewPdfBlob, closePDF: handleOnPreviewPdfClose, onClickDownload: handleDownload })))));
};
//# sourceMappingURL=TransactionAttachmentPdfStitcher.js.map