import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// (C) 2026 GoodData Corporation
import { forwardRef, useCallback, useEffect, useRef, useState, } from "react";
import { EditableLabel } from "../../EditableLabel/EditableLabel.js";
import { bem } from "../@utils/bem.js";
import { UiIconButton } from "../UiIconButton/UiIconButton.js";
import { UiTooltip } from "../UiTooltip/UiTooltip.js";
const { b, e } = bem("gd-ui-kit-inline-text-generator");
/**
 * @internal
 */
export const UiInlineTextGenerator = forwardRef(({ value, onSubmit, onCancel, onEditingStart, onChange, onGenerate, onGenerateError, onUndo, generateButtonLabel, undoButtonLabel, generatingLabel, generateButtonDataTestId, undoButtonDataTestId, dataTestId, ...editableLabelProps }, ref) => {
    const [isEditing, setIsEditing] = useState(false);
    const [isGenerating, setIsGenerating] = useState(false);
    const [generationKey, setGenerationKey] = useState(0);
    const [generatedHistory, setGeneratedHistory] = useState([]);
    const latestRequestIdRef = useRef(0);
    const latestEditableValueRef = useRef(value);
    const editableLabelRef = useRef(null);
    const submitFrameRef = useRef(null);
    const generateButtonRef = useRef(null);
    const undoButtonRef = useRef(null);
    const isActionButtonFocused = useCallback(() => {
        const activeElement = document.activeElement;
        return activeElement === generateButtonRef.current || activeElement === undoButtonRef.current;
    }, []);
    const setEditableLabelRefs = useCallback((node) => {
        editableLabelRef.current = node;
        if (typeof ref === "function") {
            ref(node);
        }
        else if (ref) {
            ref.current = node;
        }
    }, [ref]);
    useEffect(() => {
        if (!isEditing) {
            latestEditableValueRef.current = value;
        }
    }, [isEditing, value]);
    useEffect(() => {
        return () => {
            if (submitFrameRef.current !== null) {
                cancelAnimationFrame(submitFrameRef.current);
            }
            latestRequestIdRef.current += 1;
        };
    }, []);
    useEffect(() => {
        if (generationKey > 0) {
            editableLabelRef.current?.focus();
        }
    }, [generationKey]);
    const handleActionMouseDown = useCallback((event) => {
        event.preventDefault();
        event.stopPropagation();
        event.nativeEvent.stopImmediatePropagation();
    }, []);
    const handleEditingStart = useCallback(() => {
        setIsEditing(true);
        onEditingStart?.();
    }, [onEditingStart]);
    const handleCancel = useCallback((cancelledValue) => {
        latestEditableValueRef.current = cancelledValue;
        onCancel?.(cancelledValue);
        if (submitFrameRef.current !== null) {
            cancelAnimationFrame(submitFrameRef.current);
        }
        submitFrameRef.current = requestAnimationFrame(() => {
            submitFrameRef.current = null;
            setIsEditing(isActionButtonFocused());
        });
    }, [isActionButtonFocused, onCancel]);
    const handleSubmit = useCallback((submittedValue) => {
        latestEditableValueRef.current = submittedValue;
        onSubmit(submittedValue);
        if (submitFrameRef.current !== null) {
            cancelAnimationFrame(submitFrameRef.current);
        }
        submitFrameRef.current = requestAnimationFrame(() => {
            submitFrameRef.current = null;
            setIsEditing(isActionButtonFocused());
        });
    }, [isActionButtonFocused, onSubmit]);
    const handleChange = useCallback((changedValue) => {
        latestEditableValueRef.current = changedValue;
        onChange?.(changedValue);
    }, [onChange]);
    const handleGenerate = useCallback(() => {
        const valueBeforeGenerate = latestEditableValueRef.current;
        const requestId = latestRequestIdRef.current + 1;
        latestRequestIdRef.current = requestId;
        setIsGenerating(true);
        void Promise.resolve()
            .then(onGenerate)
            .then((result) => {
            if (latestRequestIdRef.current !== requestId) {
                return;
            }
            const rawGeneratedValue = result.text ?? "";
            const generatedValue = rawGeneratedValue.trim() === "" ? valueBeforeGenerate : rawGeneratedValue;
            setIsGenerating(false);
            if (generatedValue === valueBeforeGenerate) {
                return;
            }
            setGeneratedHistory((currentHistory) => [...currentHistory, valueBeforeGenerate]);
            latestEditableValueRef.current = generatedValue;
            onSubmit(generatedValue);
            setIsEditing(false);
            setGenerationKey((currentValue) => currentValue + 1);
        })
            .catch((error) => {
            if (latestRequestIdRef.current !== requestId) {
                return;
            }
            setIsGenerating(false);
            const normalizedError = error instanceof Error ? error : new Error("Failed to generate text.");
            onGenerateError?.(normalizedError);
        });
    }, [onGenerate, onGenerateError, onSubmit]);
    const handleGenerateMouseDown = useCallback((event) => {
        handleActionMouseDown(event);
        handleGenerate();
    }, [handleActionMouseDown, handleGenerate]);
    const handleGenerateClick = useCallback((event) => {
        // Mouse click is already handled on mousedown to avoid EditableLabel blur race.
        if (event.detail !== 0) {
            return;
        }
        handleGenerate();
    }, [handleGenerate]);
    const handleUndo = useCallback(() => {
        const valueToRestore = generatedHistory[generatedHistory.length - 1];
        if (valueToRestore === undefined) {
            return;
        }
        setGeneratedHistory(generatedHistory.slice(0, -1));
        latestEditableValueRef.current = valueToRestore;
        onSubmit(valueToRestore);
        setIsEditing(false);
        setGenerationKey((currentValue) => currentValue + 1);
        onUndo?.();
    }, [generatedHistory, onSubmit, onUndo]);
    const handleUndoMouseDown = useCallback((event) => {
        handleActionMouseDown(event);
        handleUndo();
    }, [handleActionMouseDown, handleUndo]);
    const handleUndoClick = useCallback((event) => {
        // Mouse click is already handled on mousedown to avoid EditableLabel blur race.
        if (event.detail !== 0) {
            return;
        }
        handleUndo();
    }, [handleUndo]);
    const handleContainerBlur = useCallback((event) => {
        const currentTarget = event.currentTarget;
        requestAnimationFrame(() => {
            if (!currentTarget.contains(document.activeElement)) {
                setIsEditing(false);
            }
        });
    }, []);
    const isGenerated = generatedHistory.length > 0;
    const isGenerateVisible = !isGenerating && isEditing;
    const isUndoVisible = !isGenerating && isEditing && isGenerated;
    const hasMultipleActions = isGenerateVisible && isUndoVisible;
    const spinnerLabel = generatingLabel ?? generateButtonLabel;
    return (_jsxs("div", { className: b({ isEditing, isGenerating, isGenerated, hasMultipleActions }), "data-testid": dataTestId, onBlur: handleContainerBlur, children: [
            _jsx(EditableLabel, { ref: setEditableLabelRefs, value: value, onSubmit: handleSubmit, onCancel: handleCancel, onEditingStart: handleEditingStart, onChange: handleChange, ...editableLabelProps }, generationKey), isGenerating ? (_jsx("div", { className: e("action"), children: _jsx(UiTooltip, { triggerBy: ["hover"], anchor: _jsx("span", { className: e("spinner"), "aria-label": spinnerLabel, children: _jsx("span", { className: "gd-spinner small" }) }), content: spinnerLabel }) })) : null, isGenerateVisible || isUndoVisible ? (_jsxs("div", { className: e("action", { hasMultipleActions }), children: [isUndoVisible ? (_jsx("div", { onMouseDown: handleUndoMouseDown, children: _jsx(UiTooltip, { triggerBy: ["hover", "focus"], anchor: _jsx(UiIconButton, { ref: undoButtonRef, icon: "undo", size: "xsmall", variant: "tertiary", dataTestId: undoButtonDataTestId, label: undoButtonLabel, onClick: handleUndoClick }), content: undoButtonLabel }) })) : null, isGenerateVisible ? (_jsx("div", { onMouseDown: handleGenerateMouseDown, children: _jsx(UiTooltip, { triggerBy: ["hover", "focus"], anchor: _jsx(UiIconButton, { ref: generateButtonRef, icon: "ai", size: "xsmall", variant: "tertiary", dataTestId: generateButtonDataTestId, label: generateButtonLabel, onClick: handleGenerateClick }), content: generateButtonLabel }) })) : null] })) : null] }));
});
UiInlineTextGenerator.displayName = "UiInlineTextGenerator";
