"use client";
import { useCallback, useRef, useState } from "react";
import { create } from "@bufbuild/protobuf";
import { UploadAttachmentRequestSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/io_pb";
import { useStigmer } from "../hooks";
import { toError } from "../internal/toError";
import { detectContentType, validateAttachmentSize, } from "./attachment-utils";
// ---------------------------------------------------------------------------
// Hook
// ---------------------------------------------------------------------------
let nextId = 0;
function generateId() {
    return `attachment-${++nextId}-${Date.now()}`;
}
/**
 * Behavior hook that manages file attachments for agent executions.
 *
 * Handles the full lifecycle: file validation, upload via
 * `stigmer.agentExecution.uploadAttachment()`, progress tracking,
 * error handling, and retry. Produces `AttachmentInput[]` ready
 * for execution creation.
 *
 * Files are uploaded immediately on selection so the `storageKey`
 * is available by the time the user submits their message.
 *
 * Platform builders who want custom attachment UI import this hook
 * directly. The {@link SessionComposer} styled component uses it
 * internally.
 *
 * @example
 * ```tsx
 * function CustomComposer() {
 *   const attachments = useAttachments({
 *     onValidationError: (msg) => toast.error(msg),
 *   });
 *
 *   return (
 *     <div>
 *       <input
 *         type="file"
 *         multiple
 *         onChange={(e) => {
 *           if (e.target.files) attachments.addFiles(e.target.files);
 *         }}
 *       />
 *       {attachments.entries.map((entry) => (
 *         <div key={entry.id}>
 *           {entry.file.name} — {entry.phase}
 *           {entry.phase === "error" && (
 *             <button onClick={() => attachments.retryEntry(entry.id)}>
 *               Retry
 *             </button>
 *           )}
 *           <button onClick={() => attachments.removeEntry(entry.id)}>
 *             Remove
 *           </button>
 *         </div>
 *       ))}
 *     </div>
 *   );
 * }
 * ```
 */
export function useAttachments(options) {
    const stigmer = useStigmer();
    const [entries, setEntries] = useState([]);
    const abortControllers = useRef(new Map());
    const uploadFile = useCallback(async (id, file, contentType) => {
        const controller = new AbortController();
        abortControllers.current.set(id, controller);
        try {
            const bytes = new Uint8Array(await file.arrayBuffer());
            if (controller.signal.aborted)
                return;
            const response = await stigmer.agentExecution.uploadAttachment(create(UploadAttachmentRequestSchema, {
                filename: file.name,
                content: bytes,
                contentType,
            }));
            if (controller.signal.aborted)
                return;
            setEntries((prev) => prev.map((e) => e.id === id
                ? { ...e, phase: "ready", storageKey: response.storageKey, error: null }
                : e));
        }
        catch (err) {
            if (controller.signal.aborted)
                return;
            const message = toError(err).message;
            setEntries((prev) => prev.map((e) => e.id === id
                ? { ...e, phase: "error", error: message }
                : e));
        }
        finally {
            abortControllers.current.delete(id);
        }
    }, [stigmer]);
    const addFiles = useCallback((files) => {
        const fileArray = Array.from(files);
        const validEntries = [];
        for (const file of fileArray) {
            const sizeError = validateAttachmentSize(file);
            if (sizeError) {
                options?.onValidationError?.(sizeError);
                continue;
            }
            const id = generateId();
            const contentType = detectContentType(file);
            validEntries.push({
                id,
                file,
                phase: "uploading",
                contentType,
                storageKey: null,
                error: null,
            });
            uploadFile(id, file, contentType);
        }
        if (validEntries.length > 0) {
            setEntries((prev) => [...prev, ...validEntries]);
        }
    }, [options, uploadFile]);
    const removeEntry = useCallback((id) => {
        const controller = abortControllers.current.get(id);
        if (controller) {
            controller.abort();
            abortControllers.current.delete(id);
        }
        setEntries((prev) => prev.filter((e) => e.id !== id));
    }, []);
    const retryEntry = useCallback((id) => {
        setEntries((prev) => {
            const entry = prev.find((e) => e.id === id);
            if (!entry || entry.phase !== "error")
                return prev;
            uploadFile(id, entry.file, entry.contentType);
            return prev.map((e) => e.id === id
                ? { ...e, phase: "uploading", error: null }
                : e);
        });
    }, [uploadFile]);
    const clear = useCallback(() => {
        for (const controller of abortControllers.current.values()) {
            controller.abort();
        }
        abortControllers.current.clear();
        setEntries([]);
    }, []);
    const toAttachmentInputs = useCallback(() => {
        return entries
            .filter((e) => e.phase === "ready" && e.storageKey !== null)
            .map((e) => ({
            filename: e.file.name,
            storageKey: e.storageKey,
            contentType: e.contentType,
        }));
    }, [entries]);
    const isUploading = entries.some((e) => e.phase === "uploading");
    const readyCount = entries.filter((e) => e.phase === "ready").length;
    const hasEntries = entries.length > 0;
    const allReady = hasEntries && readyCount === entries.length;
    return {
        entries,
        isUploading,
        readyCount,
        allReady,
        hasEntries,
        addFiles,
        removeEntry,
        retryEntry,
        clear,
        toAttachmentInputs,
    };
}
//# sourceMappingURL=useAttachments.js.map