/**
 * File Textbox — Panel-based editor combining comment text areas and file attachments.
 * Each panel is an independent comment + files group. Click "Comment/Upload Files" to add panels.
 */
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { cn } from '../../utils/cn.js';
import { use_base_form_field } from '../shared/use_base_form_field.js';
import { BaseFieldLayout } from '../shared/base_field_layout.js';
import { normalize_file_textbox_value, blocks_to_entries, entries_to_blocks } from '../../types/file_textbox.js';
import { FileTextboxPanel } from './file_textbox_panel.js';
import { ValidationDialog } from './validation_dialog.js';
import { count_files } from './utils.js';
import { HiPlus } from 'react-icons/hi';
// ============================================================================
// Main Component
// ============================================================================
export const HazoCollabFormFileTextbox = React.forwardRef((props, ref) => {
    const base = use_base_form_field(props, ref);
    if (base.should_hide)
        return null;
    const { value: raw_value, onChange, file_manager, file_accept, max_files = 50, classification_tags, classification_metadata, on_file_view, on_classify_file, classifying_file_ids, queued_file_ids, autofilling_file_ids, validation_errors, validating_file_ids, validated_file_ids, on_validation_response, external_file_response_labels, responded_clarification_ids: external_responded_ids, sent_clarifications: sent_clarifications_prop, on_validated_click, placeholder = 'Add a comment...', file_area_color, } = props;
    const blocks = normalize_file_textbox_value(raw_value);
    const entries = useMemo(() => blocks_to_entries(blocks), [blocks]);
    // Keep a ref to the latest entries so async callbacks always read current state
    const entries_ref = useRef(entries);
    entries_ref.current = entries;
    // Validation dialog state
    const [issue_dialog_file_id, set_issue_dialog_file_id] = useState(null);
    const [local_file_response_labels, set_file_response_labels] = useState({});
    // Merge external labels (from shared pending responses) with local labels
    const file_response_labels = useMemo(() => ({
        ...external_file_response_labels,
        ...local_file_response_labels,
    }), [external_file_response_labels, local_file_response_labels]);
    // --- Entry mutations (always emit flat blocks via onChange) ---
    const emit = useCallback((new_entries) => {
        onChange(entries_to_blocks(new_entries));
    }, [onChange]);
    const handle_comment_change = useCallback((entry_index, comment) => {
        const current = entries_ref.current;
        const updated = current.map((e, i) => i === entry_index ? { ...e, comment } : e);
        emit(updated);
    }, [emit]);
    const handle_files_added = useCallback((entry_index, attachments) => {
        const current = entries_ref.current;
        const updated = current.map((e, i) => {
            if (i !== entry_index)
                return e;
            const new_files = attachments.map(a => ({ type: 'file', attachment: a }));
            return { ...e, files: [...e.files, ...new_files] };
        });
        emit(updated);
    }, [emit]);
    const handle_file_remove = useCallback((entry_index, file_block_index) => {
        const current = entries_ref.current;
        const updated = current.map((e, i) => {
            if (i !== entry_index)
                return e;
            const new_files = [...e.files];
            new_files.splice(file_block_index, 1);
            return { ...e, files: new_files };
        });
        emit(updated);
    }, [emit]);
    const handle_add_panel = useCallback(() => {
        const current = entries_ref.current;
        const new_entry = {
            entry_id: `entry_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
            comment: '',
            files: [],
        };
        emit([...current, new_entry]);
    }, [emit]);
    const handle_remove_panel = useCallback((entry_index) => {
        const current = entries_ref.current;
        const updated = current.filter((_, i) => i !== entry_index);
        emit(updated);
    }, [emit]);
    const handle_download = useCallback((attachment) => {
        if (!file_manager)
            return;
        const url = file_manager.get_download_url(attachment.file_id, attachment.visibility);
        window.open(url, '_blank');
    }, [file_manager]);
    // Track locally responded clarification IDs and their response data (survives dialog close/reopen)
    const [local_responded_ids, set_local_responded_ids] = useState(new Set());
    const [local_response_data, set_local_response_data] = useState(new Map());
    // Merge local + external responded IDs for the ValidationDialog
    const merged_responded_ids = useMemo(() => {
        if (!external_responded_ids?.size && !local_responded_ids.size)
            return undefined;
        const merged = new Set(external_responded_ids);
        for (const id of local_responded_ids)
            merged.add(id);
        return merged;
    }, [external_responded_ids, local_responded_ids]);
    // Build merged sent_clarifications: external + local response data as ClarificationItem stubs
    const merged_sent_clarifications = useMemo(() => {
        const external = sent_clarifications_prop ?? [];
        if (!local_response_data.size)
            return external.length ? external : undefined;
        const external_ids = new Set(external.map(c => c.id));
        const local_stubs = [];
        for (const [id, resp] of local_response_data) {
            if (!external_ids.has(id)) {
                local_stubs.push({
                    id,
                    type: 'none',
                    status: 'responded',
                    target_field_id: '',
                    target_label: '',
                    issue_description: '',
                    doc_references: [],
                    response_options: [],
                    response_choice: resp.response_choice,
                    user_comment: resp.user_comment,
                    response_files: resp.response_files ?? [],
                    created_at: new Date().toISOString(),
                });
            }
        }
        return [...external, ...local_stubs];
    }, [sent_clarifications_prop, local_response_data]);
    // --- Validation response handlers ---
    const update_file_labels_after_response = useCallback((clarification_id, response_choice) => {
        if (!validation_errors)
            return;
        set_local_responded_ids(prev => {
            const next = new Set(prev);
            next.add(clarification_id);
            return next;
        });
        // Check if ALL errors for the file are now responded to
        for (const [file_id, items] of Object.entries(validation_errors)) {
            if (items.some(item => item.id === clarification_id)) {
                // Build set of responded IDs including this new one
                const responded = new Set(local_responded_ids);
                responded.add(clarification_id);
                const all_resolved = items.every(item => responded.has(item.id));
                if (all_resolved) {
                    set_file_response_labels(prev => ({ ...prev, [file_id]: 'resolved' }));
                }
                break;
            }
        }
    }, [validation_errors, local_responded_ids]);
    const handle_validation_respond = useCallback((clarification_id, response) => {
        on_validation_response?.(clarification_id, response);
        if (response.response_choice) {
            update_file_labels_after_response(clarification_id, response.response_choice);
        }
        // Store response data locally so it survives dialog close/reopen
        set_local_response_data(prev => {
            const next = new Map(prev);
            next.set(clarification_id, response);
            return next;
        });
        // Append response files
        if (response.response_files && response.response_files.length > 0 && issue_dialog_file_id) {
            const is_replace = response.response_choice === 'replace_document';
            const updated = entries_ref.current.map(e => {
                const original_idx = e.files.findIndex(b => b.type === 'file' && b.attachment.file_id === issue_dialog_file_id);
                if (original_idx < 0)
                    return e;
                const new_files = [...e.files];
                if (is_replace) {
                    const original = new_files[original_idx];
                    new_files[original_idx] = { ...original, replaced_by: response.response_files[0].file_id };
                }
                const new_file_blocks = response.response_files.map(att => ({
                    type: 'file', attachment: att, replaces: issue_dialog_file_id,
                }));
                new_files.splice(original_idx + 1, 0, ...new_file_blocks);
                return { ...e, files: new_files };
            });
            emit(updated);
        }
        set_issue_dialog_file_id(null);
    }, [on_validation_response, validation_errors, emit, issue_dialog_file_id]);
    const handle_validation_response_change = useCallback((clarification_id, response) => {
        on_validation_response?.(clarification_id, response);
        if (response.response_choice) {
            update_file_labels_after_response(clarification_id, response.response_choice);
            // Store response data locally so it survives dialog close/reopen
            set_local_response_data(prev => {
                const next = new Map(prev);
                next.set(clarification_id, response);
                return next;
            });
        }
    }, [on_validation_response, update_file_labels_after_response]);
    // Unresolved issue count for label badge — sum of individual unresolved errors across all files
    const unresolved_issue_count = useMemo(() => {
        if (!validation_errors)
            return 0;
        const my_file_ids = new Set(blocks.filter(b => b.type === 'file').map(b => b.attachment.file_id));
        let count = 0;
        for (const [file_id, errors] of Object.entries(validation_errors)) {
            if (my_file_ids.has(file_id) && errors.length > 0 && !file_response_labels[file_id]) {
                // Subtract individually responded errors
                const pending = merged_responded_ids
                    ? errors.filter(e => !merged_responded_ids.has(e.id)).length
                    : errors.length;
                count += pending;
            }
        }
        return count;
    }, [validation_errors, file_response_labels, blocks, merged_responded_ids]);
    const augmented_base = useMemo(() => {
        if (unresolved_issue_count === 0)
            return base;
        return {
            ...base,
            label_props: {
                ...base.label_props,
                file_error_count: (base.label_props.file_error_count || 0) + unresolved_issue_count,
            },
        };
    }, [base, unresolved_issue_count]);
    const total_file_count = count_files(blocks);
    return (_jsxs(BaseFieldLayout, { base: augmented_base, wrapper_class_name: "cls_collab_file_textbox_wrapper", children: [_jsxs("div", { className: "w-full space-y-2", children: [entries.map((entry, ei) => (_jsx(FileTextboxPanel, { entry: entry, entry_index: ei, disabled: base.is_field_disabled, placeholder: placeholder, file_manager: file_manager, file_accept: file_accept, max_files: max_files, field_id: base.field_id_final, total_file_count: total_file_count, file_area_color: file_area_color, classification_tags: classification_tags, classification_metadata: classification_metadata, classifying_file_ids: classifying_file_ids, queued_file_ids: queued_file_ids, autofilling_file_ids: autofilling_file_ids, validation_errors: validation_errors, validating_file_ids: validating_file_ids, validated_file_ids: validated_file_ids, file_response_labels: file_response_labels, on_comment_change: handle_comment_change, on_files_added: handle_files_added, on_file_remove: handle_file_remove, on_remove_panel: handle_remove_panel, on_file_view: on_file_view, on_classify_file: on_classify_file, on_download: handle_download, on_issue_click: set_issue_dialog_file_id, on_validated_click: on_validated_click, responded_ids: merged_responded_ids, file_validation_details: props.file_validation_details, file_pipeline_status: props.file_pipeline_status }, ei))), !base.is_field_disabled && (_jsxs("button", { type: "button", onClick: handle_add_panel, className: cn('inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg', 'bg-violet-500 text-xs text-white font-medium', 'hover:bg-violet-600 transition-colors'), children: [_jsx(HiPlus, { className: "h-3.5 w-3.5" }), "Comment / Upload Files"] }))] }), issue_dialog_file_id && validation_errors?.[issue_dialog_file_id] && (_jsx(ValidationDialog, { file_id: issue_dialog_file_id, blocks: blocks, validation_errors: validation_errors, file_manager: file_manager, on_respond: handle_validation_respond, on_response_change: handle_validation_response_change, on_close: () => set_issue_dialog_file_id(null), responded_clarification_ids: merged_responded_ids, sent_clarifications: merged_sent_clarifications }))] }));
});
HazoCollabFormFileTextbox.displayName = 'HazoCollabFormFileTextbox';
//# sourceMappingURL=hazo_collab_form_file_textbox.js.map