import React from 'react';
import { generateAttachmentId, readFileAsDataUrl } from '../utils/attachments';
export const useAttachmentManager = ({ cacheAttachment, removeAttachment, attachmentCallback }) => {
    const [pendingAttachments, setPendingAttachments] = React.useState([]);
    const [pendingAttachmentCallbacks, setPendingAttachmentCallbacks] = React.useState(0);
    const pendingCallbackTokensRef = React.useRef(new Set());
    const isMountedRef = React.useRef(true);
    React.useEffect(() => {
        return () => {
            isMountedRef.current = false;
        };
    }, []);
    const registerPendingCallback = React.useCallback((token) => {
        pendingCallbackTokensRef.current.add(token);
        if (isMountedRef.current) {
            setPendingAttachmentCallbacks(pendingCallbackTokensRef.current.size);
        }
    }, []);
    const completePendingCallback = React.useCallback((token) => {
        if (!pendingCallbackTokensRef.current.has(token)) {
            return;
        }
        pendingCallbackTokensRef.current.delete(token);
        if (isMountedRef.current) {
            setPendingAttachmentCallbacks(pendingCallbackTokensRef.current.size);
        }
    }, []);
    const runAttachmentCallback = React.useCallback(async (attachment) => {
        if (!attachmentCallback)
            return undefined;
        const token = `${attachment.id}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
        registerPendingCallback(token);
        let result;
        try {
            result = await attachmentCallback(attachment);
        }
        catch (error) {
            console.error('Attachment handler callback failed', error);
        }
        finally {
            completePendingCallback(token);
        }
        return result;
    }, [attachmentCallback, registerPendingCallback, completePendingCallback]);
    const processAttachment = React.useCallback((attachment) => {
        const { id, file } = attachment;
        const baseRecord = {
            id,
            name: file.name,
            mimeType: file.type || 'application/octet-stream',
            size: file.size,
            dateAdded: Date.now()
        };
        cacheAttachment(baseRecord);
        const run = async () => {
            let record = baseRecord;
            try {
                const dataUrl = await readFileAsDataUrl(file);
                setPendingAttachments((prev) => {
                    const index = prev.findIndex((entry) => entry.id === id);
                    if (index === -1)
                        return prev;
                    const next = [...prev];
                    next[index] = { ...next[index], dataUrl };
                    return next;
                });
                record = { ...record, dataUrl };
                cacheAttachment(record);
            }
            catch (error) {
                console.warn('Failed to generate preview data URL for attachment', file.name, error);
            }
            const callbackResult = await runAttachmentCallback(record);
            if (callbackResult?.sourceUrl) {
                const sourceUrl = callbackResult.sourceUrl;
                record = { ...record, sourceUrl };
                setPendingAttachments((prev) => {
                    const index = prev.findIndex((entry) => entry.id === id);
                    if (index === -1)
                        return prev;
                    const next = [...prev];
                    next[index] = { ...next[index], sourceUrl };
                    return next;
                });
            }
            cacheAttachment(record);
        };
        void run();
    }, [cacheAttachment, runAttachmentCallback]);
    const addAttachments = React.useCallback((files) => {
        if (files.length === 0)
            return;
        const attachmentsToAdd = files.map((file) => ({
            id: generateAttachmentId(),
            file
        }));
        setPendingAttachments((prev) => [...prev, ...attachmentsToAdd]);
        attachmentsToAdd.forEach(processAttachment);
    }, [processAttachment]);
    const removeAttachmentInternal = React.useCallback((attachmentId) => {
        const removed = pendingAttachments.find((attachment) => attachment.id === attachmentId);
        setPendingAttachments((prev) => prev.filter((attachment) => attachment.id !== attachmentId));
        if (removed) {
            queueMicrotask(() => {
                removeAttachment(attachmentId);
            });
        }
    }, [pendingAttachments, removeAttachment]);
    const clearAttachments = React.useCallback(() => {
        setPendingAttachments([]);
    }, []);
    const restoreAttachments = React.useCallback((attachments) => {
        setPendingAttachments([...attachments]);
    }, []);
    const chatInputAttachments = React.useMemo(() => pendingAttachments.map((attachment) => ({
        id: attachment.id,
        name: attachment.file.name,
        size: attachment.file.size,
        type: attachment.file.type || 'application/octet-stream',
        dataUrl: attachment.dataUrl,
        sourceUrl: attachment.sourceUrl
    })), [pendingAttachments]);
    const createUploads = React.useCallback(async (attachments) => {
        return await Promise.all(attachments.map(async (attachment) => {
            let dataUrl = attachment.dataUrl;
            if (!dataUrl) {
                try {
                    dataUrl = await readFileAsDataUrl(attachment.file);
                }
                catch (error) {
                    console.warn('Failed to generate data URL for attachment', attachment.file.name, error);
                }
            }
            return {
                id: attachment.id,
                name: attachment.file.name,
                mimeType: attachment.file.type || 'application/octet-stream',
                size: attachment.file.size,
                dataUrl,
                sourceUrl: attachment.sourceUrl,
                file: attachment.file,
                dateAdded: Date.now()
            };
        }));
    }, []);
    return {
        pendingAttachments,
        chatInputAttachments,
        isAttachmentCallbackPending: pendingAttachmentCallbacks > 0,
        addAttachments,
        removeAttachment: removeAttachmentInternal,
        clearAttachments,
        restoreAttachments,
        runAttachmentCallback,
        createUploads
    };
};
