/**
 * Collaboration form data table component
 * Provides a dynamic data table with inline editing, configurable columns,
 * validation, file uploads, and aggregation support
 */
'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React from 'react';
import { HiPlus, HiTrash, HiQuestionMarkCircle, HiX } from 'react-icons/hi';
import { IoDocumentAttachOutline } from 'react-icons/io5';
import { FaFileUpload, FaFileAlt } from 'react-icons/fa';
import { cn } from '../utils/cn.js';
import { attachment_to_file_data } from '../types/file_attachment.js';
import { use_logger } from '../logger/context.js';
import { optional_import } from '../utils/optional_import.js';
import { DEFAULTS } from '../config/defaults.js';
import { use_collab_form_field, CollabFormFieldContainer, CollabFormFieldLabel, CollabFormChatIcon, CollabFormFieldError, CollabFormFieldReferenceTag, CollabFormDataOkCheckbox, CollabFormNotesIcon, CollabFormEditActionsDropdown, } from './hazo_collab_form_base.js';
/** Check if a field type should be right-aligned by default */
function is_numeric_type(field_type) {
    return field_type === 'numeric' || field_type === 'currency' || field_type === 'percentage';
}
// =========================================
// UTILITY FUNCTIONS
// =========================================
/**
 * Generate a unique row ID
 */
function generate_row_id() {
    return `row_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
}
/**
 * Calculate aggregation value for a column
 */
function calculate_aggregation(column, rows) {
    if (!column.aggregation || column.aggregation.type === 'none') {
        return null;
    }
    const values = rows
        .map((row) => {
        const val = row[column.id];
        if (typeof val === 'number')
            return val;
        if (typeof val === 'string') {
            const parsed = parseFloat(val);
            return isNaN(parsed) ? null : parsed;
        }
        return null;
    })
        .filter((val) => val !== null);
    switch (column.aggregation.type) {
        case 'sum':
            return values.reduce((acc, val) => acc + val, 0);
        case 'average':
            return values.length > 0
                ? values.reduce((acc, val) => acc + val, 0) / values.length
                : 0;
        case 'count':
            return values.length;
        default:
            return null;
    }
}
/**
 * Format number for display with optional decimals
 */
function format_number(value, decimals) {
    if (decimals !== undefined) {
        return value.toFixed(decimals);
    }
    return value.toLocaleString();
}
/**
 * Validate a cell value against column constraints
 */
function validate_cell(value, column) {
    const constraints = column.constraints;
    if (!constraints)
        return undefined;
    // Required check
    if (constraints.required && (value === undefined || value === null || value === '')) {
        return 'Required';
    }
    // Skip further validation if empty and not required
    if (value === undefined || value === null || value === '') {
        return undefined;
    }
    // Numeric validations (includes currency and percentage)
    if (column.field_type === 'numeric' || column.field_type === 'currency' || column.field_type === 'percentage') {
        const num_value = typeof value === 'number' ? value : parseFloat(value);
        if (isNaN(num_value)) {
            return 'Invalid number';
        }
        if (constraints.min !== undefined && num_value < constraints.min) {
            return `Minimum: ${constraints.min}`;
        }
        if (constraints.max !== undefined && num_value > constraints.max) {
            return `Maximum: ${constraints.max}`;
        }
    }
    // Text validations
    if (column.field_type === 'text') {
        const str_value = String(value);
        if (constraints.length !== undefined && str_value.length > constraints.length) {
            return `Maximum ${constraints.length} characters`;
        }
        if (constraints.regex) {
            const regex = new RegExp(constraints.regex);
            if (!regex.test(str_value)) {
                return 'Invalid format';
            }
        }
    }
    return undefined;
}
// =========================================
// CELL RENDERER COMPONENTS
// =========================================
/**
 * Text cell renderer
 */
function TextCell({ column, value, onChange, disabled, error, }) {
    const is_editable = column.editable !== false && !disabled;
    // Render as plain text label when not editable
    if (!is_editable) {
        return (_jsx("span", { className: cn('cls_data_table_text_cell_readonly flex items-center h-8 px-2 text-sm font-medium', column.background_color), title: value || '', children: value || '' }));
    }
    return (_jsx("input", { type: "text", value: value || '', onChange: (e) => onChange(e.target.value), maxLength: column.constraints?.length, className: cn('cls_data_table_text_cell w-full h-8 px-2 text-sm border rounded-md', 'bg-transparent focus:outline-none focus:ring-1 focus:ring-ring', error && 'border-destructive', column.background_color), title: error }));
}
/**
 * Numeric cell renderer
 */
function NumericCell({ column, value, onChange, disabled, error, }) {
    const is_editable = column.editable !== false && !disabled;
    const str_value = value === undefined || value === null ? '' : String(value);
    const handle_change = (e) => {
        const input_value = e.target.value;
        // Allow empty, numbers, decimals, and negative sign
        if (input_value === '' || /^-?\d*\.?\d*$/.test(input_value)) {
            onChange(input_value);
        }
    };
    // Render as plain text label when not editable
    if (!is_editable) {
        return (_jsx("span", { className: cn('cls_data_table_numeric_cell_readonly flex items-center justify-end h-8 px-2 text-sm font-medium', column.background_color), title: str_value, children: str_value }));
    }
    return (_jsx("input", { type: "text", inputMode: "decimal", value: str_value, onChange: handle_change, className: cn('cls_data_table_numeric_cell w-full h-8 px-2 text-sm text-right border rounded-md', 'bg-transparent focus:outline-none focus:ring-1 focus:ring-ring', error && 'border-destructive', column.background_color), title: error }));
}
/**
 * Dropdown cell renderer
 */
function DropdownCell({ column, value, onChange, disabled, error, }) {
    const is_editable = column.editable !== false && !disabled;
    const options = column.options || [];
    return (_jsxs("select", { value: value || '', onChange: (e) => onChange(e.target.value), disabled: !is_editable, className: cn('cls_data_table_dropdown_cell w-full h-8 px-2 text-sm border rounded-md', 'bg-transparent focus:outline-none focus:ring-1 focus:ring-ring', !is_editable && 'cursor-not-allowed opacity-70 bg-muted', error && 'border-destructive', column.background_color), title: error, children: [_jsx("option", { value: "", children: "Select..." }), options.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }));
}
/**
 * Checkbox cell renderer
 */
function CheckboxCell({ column, value, onChange, disabled, }) {
    const is_editable = column.editable !== false && !disabled;
    const checked = value === true || value === 'true';
    return (_jsx("div", { className: "flex items-center justify-center h-8", children: _jsx("input", { type: "checkbox", checked: checked, onChange: (e) => onChange(e.target.checked), disabled: !is_editable, className: cn('cls_data_table_checkbox_cell h-4 w-4 rounded border-input', !is_editable && 'cursor-not-allowed opacity-70') }) }));
}
/**
 * Radio button cell renderer
 */
function RadioCell({ column, value, onChange, disabled, row_id, }) {
    const is_editable = column.editable !== false && !disabled;
    const options = column.options || [];
    const radio_name = `${row_id}_${column.id}`;
    return (_jsx("div", { className: "flex items-center gap-2 h-8 px-1", children: options.map((opt) => (_jsxs("label", { className: cn('flex items-center gap-1 text-xs cursor-pointer', !is_editable && 'cursor-not-allowed opacity-70'), children: [_jsx("input", { type: "radio", name: radio_name, value: opt.value, checked: value === opt.value, onChange: () => onChange(opt.value), disabled: !is_editable, className: "h-3 w-3" }), _jsx("span", { children: opt.label })] }, opt.value))) }));
}
/**
 * Files cell renderer (compact badge + modal)
 */
/**
 * Helper function to truncate filename with ellipsis
 * Keeps extension visible: "verylongfilename.pdf" -> "verylong...pdf"
 */
function truncate_filename(filename, max_length = 12) {
    if (filename.length <= max_length)
        return filename;
    const last_dot = filename.lastIndexOf('.');
    if (last_dot === -1) {
        // No extension
        return filename.slice(0, max_length - 3) + '...';
    }
    const extension = filename.slice(last_dot);
    const name = filename.slice(0, last_dot);
    const available_for_name = max_length - extension.length - 3; // 3 for "..."
    if (available_for_name <= 0) {
        return filename.slice(0, max_length - 3) + '...';
    }
    return name.slice(0, available_for_name) + '...' + extension;
}
function FilesCell({ column, files, onFilesChange, disabled, row_id, }) {
    const is_editable = column.editable !== false && !disabled;
    const file_count = files?.length || 0;
    const max_files = column.files_config?.max_files || DEFAULTS.max_files;
    const can_add_more = file_count < max_files;
    /**
     * Remove a file by index
     */
    const remove_file = (idx) => {
        if (!is_editable)
            return;
        const new_files = files.filter((_, i) => i !== idx);
        onFilesChange(new_files);
    };
    /**
     * Handle file input change
     */
    const handle_file_input = (e) => {
        const input_files = e.target.files;
        if (!input_files)
            return;
        const new_files = Array.from(input_files).map((f) => ({
            file_path: column.files_config?.target_path || '/uploads',
            file_name: f.name,
            file_size: f.size,
            file_type: f.type,
            file_id: `file_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
            uploaded_at: new Date(),
        }));
        const combined = [...(files || []), ...new_files].slice(0, max_files);
        onFilesChange(combined);
        e.target.value = '';
    };
    /**
     * Handle file click - open in new tab or download
     */
    const handle_file_click = (file) => {
        if (file.file_path) {
            // Open file in new tab
            window.open(file.file_path, '_blank', 'noopener,noreferrer');
        }
    };
    return (_jsxs("div", { className: "flex items-center gap-1 flex-wrap min-h-[32px] py-1 px-1", children: [files && files.length > 0 && files.map((file, idx) => (_jsxs("span", { className: cn('cls_data_table_file_tag inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs', 'bg-primary/10 text-primary border border-primary/20', 'max-w-[120px]'), title: file.file_name, children: [_jsx("button", { type: "button", onClick: () => handle_file_click(file), className: "truncate hover:underline cursor-pointer", title: `Open ${file.file_name}`, children: truncate_filename(file.file_name, 10) }), is_editable && (_jsx("button", { type: "button", onClick: (e) => {
                            e.stopPropagation();
                            remove_file(idx);
                        }, className: "text-primary/60 hover:text-destructive flex-shrink-0", title: "Remove file", children: _jsx(HiX, { className: "h-3 w-3" }) }))] }, file.file_id || idx))), is_editable && can_add_more && (_jsxs(_Fragment, { children: [_jsx("input", { type: "file", multiple: true, accept: column.files_config?.file_accept, onChange: handle_file_input, className: "hidden", id: `file-input-${row_id}-${column.id}` }), _jsx("label", { htmlFor: `file-input-${row_id}-${column.id}`, className: cn('cls_data_table_add_file inline-flex items-center justify-center px-1.5 py-0.5 rounded text-xs cursor-pointer', 'border border-dashed border-input text-muted-foreground hover:border-primary hover:text-primary', 'transition-colors'), title: "Add files", children: _jsx(IoDocumentAttachOutline, { className: "h-4 w-4" }) })] })), file_count === 0 && !is_editable && (_jsx("span", { className: "text-xs text-muted-foreground", children: "No files" }))] }));
}
// =========================================
// TOOLTIP COMPONENT
// =========================================
/**
 * Column header tooltip using HoverCard
 */
function ColumnTooltip({ tooltip, }) {
    const logger = use_logger();
    const [HoverCardComponents, setHoverCardComponents] = React.useState(null);
    React.useEffect(() => {
        const loadComponents = async () => {
            try {
                const hoverCardModule = await import('hazo_ui').catch(() => null);
                if (hoverCardModule) {
                    setHoverCardComponents({
                        HoverCard: hoverCardModule.HoverCard,
                        HoverCardTrigger: hoverCardModule.HoverCardTrigger,
                        HoverCardContent: hoverCardModule.HoverCardContent,
                    });
                }
            }
            catch (error) {
                logger.warn('[ColumnTooltip] Error loading HoverCard', {
                    error: error instanceof Error ? error.message : String(error),
                });
            }
        };
        loadComponents();
    }, []);
    if (!HoverCardComponents) {
        return (_jsx("span", { title: tooltip.content, children: _jsx(HiQuestionMarkCircle, { className: "h-4 w-4 text-muted-foreground" }) }));
    }
    const { HoverCard, HoverCardTrigger, HoverCardContent } = HoverCardComponents;
    return (_jsxs(HoverCard, { children: [_jsx(HoverCardTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex", children: _jsx(HiQuestionMarkCircle, { className: "h-4 w-4 text-muted-foreground hover:text-foreground" }) }) }), _jsxs(HoverCardContent, { className: "w-64", children: [tooltip.title && (_jsx("h4", { className: "font-medium text-sm mb-1", children: tooltip.title })), _jsx("p", { className: "text-sm text-muted-foreground", children: tooltip.content })] })] }));
}
// =========================================
// ROW FILE ICON COMPONENT
// =========================================
/**
 * Row-level file icon with popover for viewing/uploading files per row.
 * - No files: grey FaFileUpload icon
 * - Has files: blue FaFileAlt icon + count badge
 * - Click opens Radix Popover with file list + upload button
 */
/**
 * Convert FormFileAttachment[] to hazo_pdf FileItem[] format
 */
function attachments_to_file_items(attachments, get_download_url) {
    return attachments.map((a) => {
        const url = get_download_url ? get_download_url(a.file_id, a.visibility) : '';
        const mime = (a.mime_type || '').toLowerCase();
        return {
            id: a.file_id,
            name: a.file_name,
            url,
            type: mime === 'application/pdf' ? 'pdf'
                : mime.startsWith('image/') ? 'image'
                    : 'other',
            mime_type: a.mime_type || 'application/octet-stream',
            file_path: url,
            size: a.file_size || 0,
        };
    });
}
function RowFileIcon({ row_files, on_files_change, file_manager, disabled, max_files = 10, row_label, }) {
    const [dialog_open, set_dialog_open] = React.useState(false);
    const file_count = row_files.length;
    const has_files = file_count > 0;
    // Dynamic import of PdfViewerDialog from hazo_pdf
    const [PdfDialogComponent, set_pdf_dialog] = React.useState(null);
    React.useEffect(() => {
        let cancelled = false;
        optional_import('hazo_pdf').then((mod) => {
            if (!cancelled && mod.PdfViewerDialog) {
                set_pdf_dialog(() => mod.PdfViewerDialog);
            }
        }).catch(() => {
            // hazo_pdf not installed
        });
        return () => { cancelled = true; };
    }, []);
    // Convert row files to hazo_pdf file items
    const file_items = React.useMemo(() => attachments_to_file_items(row_files, file_manager.get_download_url), [row_files, file_manager.get_download_url]);
    // Upload handler for PdfViewerDialog
    const handle_dialog_upload = React.useCallback(async (file) => {
        if (!file_manager.upload)
            return;
        try {
            const attachment = await file_manager.upload(file, {
                entity_id: row_label,
                visibility: 'public',
            });
            const combined = [...row_files, attachment].slice(0, max_files);
            on_files_change(combined);
            return attachment;
        }
        catch (err) {
            console.error('[RowFileIcon] Upload failed:', err);
        }
    }, [file_manager, row_label, row_files, max_files, on_files_change]);
    // Delete handler for PdfViewerDialog
    const handle_dialog_delete = React.useCallback((file_id) => {
        const file = row_files.find(f => f.file_id === file_id);
        if (file && file_manager.remove) {
            file_manager.remove(file.file_id, file.ref_id).catch((err) => {
                console.error('[RowFileIcon] Remove failed:', err);
            });
        }
        on_files_change(row_files.filter(f => f.file_id !== file_id));
    }, [file_manager, row_files, on_files_change]);
    const handle_click = () => {
        if (PdfDialogComponent) {
            set_dialog_open(true);
        }
    };
    return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", disabled: disabled || !PdfDialogComponent, onClick: handle_click, className: cn('cls_row_file_icon relative flex items-center justify-center h-8 w-8 rounded-md', 'focus:outline-none focus:ring-1 focus:ring-ring', disabled && 'cursor-not-allowed opacity-50', has_files
                    ? 'text-blue-600 hover:bg-blue-50'
                    : 'text-muted-foreground hover:text-foreground hover:bg-accent'), title: has_files ? `${file_count} file(s) attached` : 'Upload file', children: has_files ? (_jsxs(_Fragment, { children: [_jsx(FaFileAlt, { className: "h-4 w-4 flex-shrink-0" }), _jsx("span", { className: "absolute -top-1 -right-1 bg-blue-600 text-white text-[10px] font-bold rounded-full h-4 w-4 flex items-center justify-center", children: file_count })] })) : (_jsx(FaFileUpload, { className: "h-4 w-4 flex-shrink-0" })) }), PdfDialogComponent && dialog_open && (_jsx(PdfDialogComponent, { open: true, on_open_change: (open) => { if (!open)
                    set_dialog_open(false); }, files: file_items, on_upload: handle_dialog_upload, on_file_delete: handle_dialog_delete, toolbar_enabled: true, show_save_button: false, direct_upload: true, on_close: () => set_dialog_open(false), viewer_title: `${row_label} - Files`, dialog_width: "90vw", dialog_height: "85vh" }))] }));
}
// =========================================
// MAIN COMPONENT
// =========================================
/**
 * Collaboration form data table component
 */
export const HazoCollabFormDataTable = React.forwardRef((props, ref) => {
    const { label, error, field_id, field_data_id, field_name, table_config, value, onChange, table_class_name, header_class_name, row_class_name, cell_class_name, disabled, on_chat_click, chat_status, is_chat_active, chat_background_color = 'bg-muted', is_data_ok_default, container_class_name, label_class_name, label_actions, error_class_name, required, data_ok_checked, on_data_ok_change, data_ok_mode, data_ok_value, on_data_ok_value_change, data_ok_default, data_ok_hidden_states, data_ok_editable, disable_data_ok, disable_chat, enable_notes, disable_notes, notes, on_notes_change, has_notes, notes_panel_style, notes_background_color, notes_save_mode, current_user, id, hazo_chat_group_id, hazo_chat_reference_id, hazo_chat_reference_type, hazo_chat_api_base_url, hazo_chat_timezone, hazo_chat_title, hazo_chat_subtitle, hazo_chat_realtime_mode, hazo_chat_polling_interval, hazo_chat_messages_per_page, hazo_chat_class_name, hazo_chat_on_close, hazo_chat_is_open, hazo_chat_on_open_change, hazo_chat_show_sidebar_toggle, hazo_chat_show_delete_button, hazo_chat_bubble_radius, reference_value, reference_label, reference_tag_background_color, on_row_chat_click, on_row_notes_change, 
    // File manager for row files
    file_manager, 
    // Visibility toggle props
    enable_visibility_toggle, disable_visibility_toggle, visibility = 'visible', on_visibility_change, 
    // Lock props
    enable_lock, disable_lock, locked, on_lock_change, 
    // Delete props
    enable_delete, disable_delete, on_delete, 
    // User role for author controls
    user_role = 'responder', 
    // Edit actions display mode
    edit_actions_display, action_buttons_borderless, 
    // Dropdown consolidation props
    include_chat_in_dropdown, include_notes_in_dropdown, extract_active_chat, extract_active_notes, } = props;
    const logger = use_logger();
    // Initialize rows with empty array if undefined, ensuring each row has a _row_id
    const rows = React.useMemo(() => {
        const raw = value || [];
        let needs_ids = false;
        for (const row of raw) {
            if (!row._row_id) {
                needs_ids = true;
                break;
            }
        }
        if (!needs_ids)
            return raw;
        return raw.map((row) => row._row_id ? row : { ...row, _row_id: generate_row_id() });
    }, [value]);
    // Cell validation errors state
    const [cell_errors, set_cell_errors] = React.useState({});
    // Row-level chat state - tracks which row's chat is currently open
    const [active_row_chat, set_active_row_chat] = React.useState(null);
    // Dynamic import for HazoChat component
    const [HazoChatComponent, setHazoChatComponent] = React.useState(null);
    // Use the common collab form field hook
    const { field_id_final, handle_chat_icon_click, handle_chat_close, chat_is_open, is_chat_disabled } = use_collab_form_field({
        label,
        field_id,
        id,
        field_data_id,
        field_name,
        on_chat_click,
        hazo_chat_group_id,
        hazo_chat_on_open_change,
        hazo_chat_is_open,
        hazo_chat_on_close,
    });
    // Config defaults
    const columns = table_config.columns || [];
    const allow_add_row = table_config.allow_add_row !== false;
    const allow_delete_row = table_config.allow_delete_row !== false;
    const show_row_numbers = table_config.show_row_numbers === true;
    const enable_row_collab = table_config.enable_row_collab !== false;
    const max_rows = table_config.max_rows;
    const empty_message = table_config.empty_message || 'No data. Click "Add Row" to begin.';
    // Row files config
    const has_row_files = (table_config.enable_row_files === true) && !!file_manager;
    const max_row_files = table_config.max_row_files ?? 10;
    // Check if any row action is actually enabled
    const has_row_data_ok = enable_row_collab && !disable_data_ok;
    const has_row_notes = enable_row_collab && enable_notes && !disable_notes;
    const has_row_chat = enable_row_collab && !disable_chat;
    const show_actions_column = has_row_data_ok || has_row_notes || has_row_chat || has_row_files || allow_delete_row;
    // Load HazoChat dynamically when row chat is enabled
    React.useEffect(() => {
        if (has_row_chat && hazo_chat_group_id && !HazoChatComponent) {
            const loadHazoChat = async () => {
                try {
                    const module = await import('hazo_chat');
                    if (module.HazoChat) {
                        setHazoChatComponent(() => module.HazoChat);
                    }
                }
                catch (error) {
                    logger.warn('[HazoCollabFormDataTable] HazoChat not available', {
                        error: error instanceof Error ? error.message : String(error),
                    });
                }
            };
            loadHazoChat();
        }
    }, [has_row_chat, hazo_chat_group_id, HazoChatComponent]);
    // Check if any column has aggregation
    const has_aggregations = columns.some((col) => col.aggregation && col.aggregation.type !== 'none');
    const show_subtotal_row = table_config.show_subtotal_row !== false && has_aggregations;
    /**
     * Add a new row
     */
    const add_row = React.useCallback(() => {
        if (max_rows && rows.length >= max_rows) {
            return;
        }
        const new_row = {
            _row_id: generate_row_id(),
        };
        // Initialize default values for each column
        columns.forEach((col) => {
            if (col.field_type === 'checkbox') {
                new_row[col.id] = false;
            }
            else if (col.field_type === 'files') {
                // Files are stored in _files
            }
            else {
                new_row[col.id] = '';
            }
        });
        onChange([...rows, new_row]);
    }, [rows, columns, max_rows, onChange]);
    /**
     * Delete a row
     */
    const delete_row = React.useCallback((row_id) => {
        onChange(rows.filter((row) => row._row_id !== row_id));
        // Clean up errors for deleted row
        set_cell_errors((prev) => {
            const updated = { ...prev };
            delete updated[row_id];
            return updated;
        });
    }, [rows, onChange]);
    /**
     * Update a cell value
     */
    const update_cell = React.useCallback((row_id, column_id, value) => {
        const updated_rows = rows.map((row) => {
            if (row._row_id === row_id) {
                return { ...row, [column_id]: value };
            }
            return row;
        });
        onChange(updated_rows);
        // Validate the cell
        const column = columns.find((c) => c.id === column_id);
        if (column) {
            const error = validate_cell(value, column);
            set_cell_errors((prev) => {
                const row_errors = { ...prev[row_id] };
                if (error) {
                    row_errors[column_id] = error;
                }
                else {
                    delete row_errors[column_id];
                }
                return { ...prev, [row_id]: row_errors };
            });
        }
    }, [rows, columns, onChange]);
    /**
     * Update files for a cell
     */
    const update_files = React.useCallback((row_id, column_id, files) => {
        const updated_rows = rows.map((row) => {
            if (row._row_id === row_id) {
                return {
                    ...row,
                    _files: {
                        ...(row._files || {}),
                        [column_id]: files,
                    },
                };
            }
            return row;
        });
        onChange(updated_rows);
    }, [rows, onChange]);
    /**
     * Update row-level files
     */
    const update_row_files = React.useCallback((row_id, files) => {
        const updated_rows = rows.map((row) => {
            if (row._row_id === row_id) {
                return { ...row, _row_files: files };
            }
            return row;
        });
        onChange(updated_rows);
    }, [rows, onChange]);
    /**
     * Get all file data from the table (column files + row files)
     */
    const get_file_data = React.useCallback(() => {
        const all_files = [];
        rows.forEach((row) => {
            if (row._files) {
                Object.values(row._files).forEach((files) => {
                    all_files.push(...files);
                });
            }
            if (row._row_files) {
                row._row_files.forEach((attachment) => {
                    all_files.push(attachment_to_file_data(attachment));
                });
            }
        });
        return all_files;
    }, [rows]);
    /**
     * Get computed aggregation values
     */
    const get_aggregations = React.useCallback(() => {
        const aggregations = {};
        columns.forEach((col) => {
            const result = calculate_aggregation(col, rows);
            if (result !== null) {
                aggregations[col.id] = result;
            }
        });
        return aggregations;
    }, [columns, rows]);
    // Expose ref methods
    React.useImperativeHandle(ref, () => ({
        get_file_data,
        add_row,
        delete_row,
        get_aggregations,
    }), [get_file_data, add_row, delete_row, get_aggregations]);
    /**
     * Render a cell based on field type
     */
    const render_cell = (row, column) => {
        const cell_error = cell_errors[row._row_id]?.[column.id];
        switch (column.field_type) {
            case 'text':
                return (_jsx(TextCell, { column: column, value: row[column.id] || '', onChange: (val) => update_cell(row._row_id, column.id, val), disabled: disabled, error: cell_error }));
            case 'numeric':
                return (_jsx(NumericCell, { column: column, value: row[column.id], onChange: (val) => update_cell(row._row_id, column.id, val), disabled: disabled, error: cell_error }));
            case 'dropdown':
                return (_jsx(DropdownCell, { column: column, value: row[column.id] || '', onChange: (val) => update_cell(row._row_id, column.id, val), disabled: disabled, error: cell_error }));
            case 'checkbox':
                return (_jsx(CheckboxCell, { column: column, value: row[column.id], onChange: (val) => update_cell(row._row_id, column.id, val), disabled: disabled }));
            case 'radiobutton':
                return (_jsx(RadioCell, { column: column, value: row[column.id] || '', onChange: (val) => update_cell(row._row_id, column.id, val), disabled: disabled, row_id: row._row_id }));
            case 'files':
                return (_jsx(FilesCell, { column: column, files: row._files?.[column.id] || [], onFilesChange: (files) => update_files(row._row_id, column.id, files), disabled: disabled, row_id: row._row_id }));
            case 'currency':
                return (_jsx(NumericCell, { column: column, value: row[column.id], onChange: (val) => update_cell(row._row_id, column.id, val), disabled: disabled, error: cell_error }));
            case 'percentage':
                return (_jsx(NumericCell, { column: column, value: row[column.id], onChange: (val) => update_cell(row._row_id, column.id, val), disabled: disabled, error: cell_error }));
            default:
                return _jsx("span", { className: "text-sm text-muted-foreground", children: "Unsupported" });
        }
    };
    /**
     * Render column header with optional tooltip
     */
    const render_header = (column) => {
        const styling = column.header_styling || {};
        return (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: cn('text-sm', styling.bold && 'font-bold', styling.italic && 'italic', styling.size, styling.color), children: column.label }), column.tooltip?.enabled && _jsx(ColumnTooltip, { tooltip: column.tooltip })] }));
    };
    return (_jsxs(CollabFormFieldContainer, { chat_status: chat_status, is_chat_active: is_chat_active, chat_background_color: chat_background_color, is_data_ok_default: is_data_ok_default, container_class_name: container_class_name, force_full_row: true, hazo_chat_is_open: chat_is_open, hazo_chat_group_id: hazo_chat_group_id, hazo_chat_reference_id: hazo_chat_reference_id, hazo_chat_reference_type: hazo_chat_reference_type, hazo_chat_api_base_url: hazo_chat_api_base_url, hazo_chat_timezone: hazo_chat_timezone, hazo_chat_title: hazo_chat_title, hazo_chat_subtitle: hazo_chat_subtitle, hazo_chat_realtime_mode: hazo_chat_realtime_mode, hazo_chat_polling_interval: hazo_chat_polling_interval, hazo_chat_messages_per_page: hazo_chat_messages_per_page, hazo_chat_class_name: hazo_chat_class_name, hazo_chat_on_close: handle_chat_close, hazo_chat_show_sidebar_toggle: hazo_chat_show_sidebar_toggle, hazo_chat_show_delete_button: hazo_chat_show_delete_button, hazo_chat_bubble_radius: hazo_chat_bubble_radius, field_data_id: field_data_id, field_name: field_name, label: label, children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(CollabFormFieldLabel, { field_id_final: field_id_final, label: label, label_class_name: label_class_name, required: required, label_actions: label_actions }), _jsxs("div", { className: "flex items-center gap-2", children: [!disable_data_ok && (_jsx(CollabFormDataOkCheckbox, { label: label, data_ok_checked: data_ok_checked, on_data_ok_change: on_data_ok_change, data_ok_mode: data_ok_mode, data_ok_value: data_ok_value, on_data_ok_value_change: on_data_ok_value_change, data_ok_default: data_ok_default, data_ok_hidden_states: data_ok_hidden_states, editable: data_ok_editable, borderless: action_buttons_borderless })), _jsx(CollabFormEditActionsDropdown, { label: label, field_id: field_data_id || field_id_final, user_role: user_role, enable_lock: enable_lock, disable_lock: disable_lock, locked: locked, on_lock_change: on_lock_change, enable_visibility_toggle: enable_visibility_toggle, disable_visibility_toggle: disable_visibility_toggle, visibility: visibility, on_visibility_change: on_visibility_change, enable_delete: enable_delete, disable_delete: disable_delete, on_delete: on_delete, edit_actions_display: edit_actions_display, borderless: action_buttons_borderless, 
                                // Chat consolidation props
                                include_chat_in_dropdown: include_chat_in_dropdown, enable_chat: !disable_chat, disable_chat: disable_chat, chat_status: chat_status, on_chat_click: handle_chat_icon_click, extract_active_chat: extract_active_chat, 
                                // Notes consolidation props
                                include_notes_in_dropdown: include_notes_in_dropdown, enable_notes: enable_notes, disable_notes: disable_notes, has_notes: has_notes, notes: notes, on_notes_change: on_notes_change, current_user: current_user, field_data_id: field_data_id, extract_active_notes: extract_active_notes })] })] }), _jsx(CollabFormFieldReferenceTag, { reference_value: reference_value, reference_label: reference_label, reference_tag_background_color: reference_tag_background_color }), _jsx("div", { className: "cls_data_table_wrapper overflow-x-auto border rounded-md", children: _jsxs("table", { className: cn('cls_data_table w-full border-collapse', table_class_name), children: [_jsx("thead", { children: _jsxs("tr", { className: cn('cls_data_table_header bg-muted/50', header_class_name), children: [show_row_numbers && (_jsx("th", { className: "cls_data_table_row_num_header w-10 px-2 py-2 text-left text-xs font-medium text-muted-foreground border-b", children: "#" })), columns.map((column) => (_jsx("th", { className: cn('cls_data_table_col_header px-2 py-2 border-b', is_numeric_type(column.field_type) ? 'text-right' : 'text-left', column.width, column.background_color), children: render_header(column) }, column.id))), show_actions_column && (_jsx("th", { className: "cls_data_table_actions_header w-24 px-2 py-2 text-center text-xs font-medium text-muted-foreground border-b", children: "Actions" }))] }) }), _jsxs("tbody", { children: [rows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: columns.length +
                                            (show_row_numbers ? 1 : 0) +
                                            (enable_row_collab || allow_delete_row ? 1 : 0), className: "px-4 py-8 text-center text-sm text-muted-foreground", children: empty_message }) }, "empty-message")) : (rows.map((row, row_index) => (_jsxs("tr", { className: cn('cls_data_table_row border-b last:border-b-0 hover:bg-muted/30', row._has_chat_messages && 'bg-destructive/10 hover:bg-destructive/15', row_class_name), children: [show_row_numbers && (_jsx("td", { className: "cls_data_table_row_num w-10 px-2 py-1 text-xs text-muted-foreground", children: row_index + 1 })), columns.map((column) => (_jsx("td", { className: cn('cls_data_table_cell px-1 py-1', column.width, cell_class_name), children: render_cell(row, column) }, column.id))), show_actions_column && (_jsx("td", { className: "cls_data_table_row_actions px-1 py-1", children: _jsxs("div", { className: "flex items-center justify-center gap-1", children: [has_row_data_ok && (_jsx(CollabFormDataOkCheckbox, { label: `Row ${row_index + 1}`, data_ok_checked: row._data_ok, on_data_ok_change: (checked) => {
                                                            const updated_rows = rows.map((r) => r._row_id === row._row_id
                                                                ? { ...r, _data_ok: checked }
                                                                : r);
                                                            onChange(updated_rows);
                                                        }, data_ok_default: data_ok_default, data_ok_hidden_states: data_ok_hidden_states, editable: data_ok_editable })), has_row_notes && (_jsx(CollabFormNotesIcon, { label: `Row ${row_index + 1}`, has_notes: row._has_notes, notes: row._notes, on_notes_change: (notes_entries) => {
                                                            // Update row notes and has_notes flag
                                                            const updated_rows = rows.map((r) => r._row_id === row._row_id
                                                                ? { ...r, _notes: notes_entries, _has_notes: notes_entries.length > 0 }
                                                                : r);
                                                            onChange(updated_rows);
                                                            // Also call the external callback if provided
                                                            on_row_notes_change?.(row._row_id, notes_entries);
                                                        }, current_user: current_user, field_data_id: row._row_id, panel_style: notes_panel_style, background_color: notes_background_color, save_mode: notes_save_mode })), has_row_chat && (_jsx(CollabFormChatIcon, { label: `Row ${row_index + 1}`, error: error, has_chat_messages: row._has_chat_messages, on_click: () => {
                                                            // Open row-level chat if hazo_chat_group_id is configured
                                                            if (hazo_chat_group_id) {
                                                                set_active_row_chat({ row_id: row._row_id, row_index });
                                                            }
                                                            // Also call the external callback if provided
                                                            on_row_chat_click?.(row._row_id, row_index);
                                                        } })), has_row_files && file_manager && (_jsx(RowFileIcon, { row_files: row._row_files || [], on_files_change: (files) => update_row_files(row._row_id, files), file_manager: file_manager, disabled: disabled, max_files: max_row_files, row_label: `Row ${row_index + 1}` })), allow_delete_row && (_jsx("button", { type: "button", onClick: () => delete_row(row._row_id), disabled: disabled, className: cn('cls_data_table_delete_btn flex items-center justify-center h-8 w-8 rounded-md', 'text-muted-foreground hover:text-destructive hover:bg-destructive/10', 'focus:outline-none focus:ring-1 focus:ring-ring', disabled && 'cursor-not-allowed opacity-50'), title: "Delete row", children: _jsx(HiTrash, { className: "h-4 w-4" }) }))] }) }))] }, row._row_id)))), show_subtotal_row && rows.length > 0 && (_jsxs("tr", { className: "cls_data_table_subtotal_row bg-muted/50 font-medium", children: [show_row_numbers && _jsx("td", { className: "px-2 py-2" }), columns.map((column, idx) => {
                                            const agg_value = calculate_aggregation(column, rows);
                                            const agg_label = column.aggregation?.label || 'Total';
                                            return (_jsx("td", { className: cn('cls_data_table_subtotal_cell px-2 py-2 text-sm', is_numeric_type(column.field_type) && 'text-right'), children: agg_value !== null && (_jsx("span", { children: format_number(agg_value, column.constraints?.num_decimals) })) }, column.id));
                                        }), show_actions_column && _jsx("td", { className: "px-2 py-2" })] }, "subtotal-row"))] })] }) }), allow_add_row && (_jsxs("div", { className: "cls_data_table_add_row_wrapper mt-2", children: [_jsxs("button", { type: "button", onClick: add_row, disabled: disabled || (max_rows !== undefined && rows.length >= max_rows), className: cn('cls_data_table_add_row_btn flex items-center gap-1 px-3 py-1.5 rounded-md text-sm', 'border border-input bg-transparent hover:bg-accent', 'focus:outline-none focus:ring-1 focus:ring-ring', 'disabled:cursor-not-allowed disabled:opacity-50'), children: [_jsx(HiPlus, { className: "h-4 w-4" }), "Add Row"] }), max_rows !== undefined && (_jsxs("span", { className: "text-xs text-muted-foreground ml-2", children: [rows.length, "/", max_rows, " rows"] }))] })), _jsx(CollabFormFieldError, { field_id_final: field_id_final, error: error, error_class_name: error_class_name }), active_row_chat && hazo_chat_group_id && HazoChatComponent && (_jsxs("div", { className: cn('cls_data_table_row_chat mt-4 border rounded-lg overflow-hidden', chat_background_color), children: [_jsxs("div", { className: "cls_data_table_row_chat_header flex items-center justify-between px-4 py-2 border-b bg-background", children: [_jsxs("span", { className: "text-sm font-medium", children: ["Chat - Row ", active_row_chat.row_index + 1] }), _jsx("button", { type: "button", onClick: () => set_active_row_chat(null), className: "text-muted-foreground hover:text-foreground", title: "Close chat", children: _jsx(HiX, { className: "h-4 w-4" }) })] }), _jsx("div", { className: "cls_data_table_row_chat_content h-[400px]", children: _jsx(HazoChatComponent, { chat_group_id: hazo_chat_group_id, reference_id: `${hazo_chat_reference_id || field_id_final}_row_${active_row_chat.row_id}`, reference_type: hazo_chat_reference_type || 'table_row', api_base_url: hazo_chat_api_base_url, timezone: hazo_chat_timezone, title: `${hazo_chat_title || label} - Row ${active_row_chat.row_index + 1}`, subtitle: hazo_chat_subtitle, realtime_mode: hazo_chat_realtime_mode, polling_interval: hazo_chat_polling_interval, messages_per_page: hazo_chat_messages_per_page, show_sidebar_toggle: hazo_chat_show_sidebar_toggle, show_delete_button: hazo_chat_show_delete_button, bubble_radius: hazo_chat_bubble_radius, className: cn('h-full w-full', hazo_chat_class_name) }) })] }))] }));
});
HazoCollabFormDataTable.displayName = 'HazoCollabFormDataTable';
//# sourceMappingURL=hazo_collab_form_data_table.js.map