import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React from "react";
import { Provider, createStore } from "jotai";
import { useEffect, useRef, useState } from "react";
import { chatInputErrorAtom, chatInputModeAtom, chatInputStatusAtom, chatInputTextAtom, chatInputTranscriptAtom, } from "../atoms/chatInputAtoms";
import { waveformLevelsAtom } from "../atoms/voiceAtoms";
import { attachmentListAtom } from "../atoms/attachmentAtoms";
import { mergeChatInputTokens } from "../tokens/defaultTokens";
import { useAttachmentState } from "../hooks/useAttachmentState";
import { useChatInputState } from "../hooks/useChatInputState";
import { useVoiceInputController } from "../hooks/useVoiceInputController";
import { AttachmentPreview } from "./AttachmentPreview";
import { EmojiPicker } from "./EmojiPicker";
import { EmojiTrigger } from "./EmojiTrigger";
import { HoldToTalkButton } from "./HoldToTalkButton";
import { ImageTrigger } from "./ImageTrigger";
import { InputSurface } from "./InputSurface";
import { SendAction } from "./SendAction";
import { StatusHint } from "./StatusHint";
import { TextComposer } from "./TextComposer";
import { WaveformFeedback } from "./WaveformFeedback";
import { KeyboardOutlineIcon, MicOutlineIcon } from "./icons";
function MobileInner(props) {
    const tokens = mergeChatInputTokens(props.tokens);
    const state = useChatInputState();
    const attachments = useAttachmentState();
    const [recordingChoice, setRecordingChoice] = useState("send");
    const [isEmojiOpen, setIsEmojiOpen] = useState(false);
    const [isUploadingImage, setIsUploadingImage] = useState(false);
    const cancelZoneRef = useRef(null);
    const transcribeZoneRef = useRef(null);
    const textComposerRef = useRef(null);
    const emojiAnchorRef = useRef(null);
    const imageInputRef = useRef(null);
    const voice = useVoiceInputController({
        ...props.voice,
        onVoiceSend: async (blob) => {
            await props.onSend?.({
                text: "",
                attachments: state.attachments,
                audio: blob,
                mode: "voice",
            });
        },
    });
    useEffect(() => {
        if (props.value !== undefined) {
            state.setText(props.value);
        }
    }, [props.value]);
    const statusText = state.status === "recording"
        ? "正在录音"
        : state.status === "transcribing"
            ? "正在转写..."
            : (state.error ?? (isUploadingImage ? "正在上传图片..." : state.transcript) ?? undefined);
    const onSend = async () => {
        if (!props.onSend) {
            return;
        }
        state.setStatus("sending");
        await props.onSend({
            text: state.text,
            attachments: state.attachments,
            transcript: state.transcript || undefined,
            mode: "text",
        });
        state.setText("");
        state.setTranscript("");
        state.setAttachments([]);
        props.onChange?.("");
        state.setStatus("idle");
    };
    const handleImageFile = async (file) => {
        if (!props.image?.uploadImage) {
            attachments.addAttachment({
                name: file.name,
                file,
                previewUrl: URL.createObjectURL(file),
            });
            return;
        }
        setIsUploadingImage(true);
        state.setError(null);
        try {
            const uploaded = await props.image.uploadImage(file);
            attachments.addAttachment({
                name: uploaded.name ?? file.name,
                file,
                url: uploaded.url,
                previewUrl: uploaded.previewUrl ?? uploaded.url,
            });
        }
        catch (error) {
            state.setError(error instanceof Error ? error.message : "Failed to upload image");
            state.setStatus("error");
        }
        finally {
            setIsUploadingImage(false);
        }
    };
    const isRecordingOverlayVisible = state.status === "recording" || state.status === "transcribing";
    const updateRecordingChoice = (clientX, clientY) => {
        const isInside = (node) => {
            if (!node) {
                return false;
            }
            const rect = node.getBoundingClientRect();
            const inset = 20;
            return (clientX >= rect.left - inset &&
                clientX <= rect.right + inset &&
                clientY >= rect.top - inset &&
                clientY <= rect.bottom + inset);
        };
        if (isInside(cancelZoneRef.current)) {
            setRecordingChoice("cancel");
            return;
        }
        if (isInside(transcribeZoneRef.current)) {
            setRecordingChoice("transcribe");
            return;
        }
        setRecordingChoice("send");
    };
    const insertEmoji = (emoji) => {
        const textarea = textComposerRef.current;
        const start = textarea?.selectionStart ?? state.text.length;
        const end = textarea?.selectionEnd ?? state.text.length;
        const nextText = `${state.text.slice(0, start)}${emoji}${state.text.slice(end)}`;
        state.setText(nextText);
        state.setStatus(nextText.trim() ? "typing" : "idle");
        props.onChange?.(nextText);
        requestAnimationFrame(() => {
            textarea?.focus();
            const caret = start + emoji.length;
            textarea?.setSelectionRange(caret, caret);
        });
    };
    return (_jsxs("div", { style: {
            position: "relative",
            width: "100%",
            maxWidth: 420,
            padding: 0,
            background: "#ECE9E3",
            borderRadius: 0,
            border: 0,
            boxShadow: "none",
            overflow: "visible",
        }, children: [isRecordingOverlayVisible ? (_jsxs("div", { style: {
                    position: "absolute",
                    left: 0,
                    right: 0,
                    bottom: 72,
                    height: 250,
                    pointerEvents: "none",
                    background: "linear-gradient(180deg, rgba(22, 16, 45, 0) 0%, rgba(22, 16, 45, 0.24) 34%, rgba(22, 16, 45, 0.6) 100%)",
                    borderRadius: 28,
                }, children: [_jsxs("div", { style: {
                            position: "absolute",
                            left: "50%",
                            transform: "translateX(-50%)",
                            bottom: 126,
                            width: 188,
                            padding: "18px 18px 22px",
                            borderRadius: 26,
                            background: recordingChoice === "transcribe" ? "#E7DCFF" : "#F3EEFF",
                            boxShadow: "0 18px 40px rgba(40, 22, 102, 0.18)",
                            display: "grid",
                            justifyItems: "center",
                            gap: 8,
                        }, children: [_jsx(WaveformFeedback, { levels: voice.waveformLevels, tokens: tokens, compact: true }), _jsx("div", { style: {
                                    color: recordingChoice === "transcribe" ? "#5B35D4" : "#6D4AFF",
                                    fontSize: 13,
                                    lineHeight: "18px",
                                    fontWeight: 600,
                                }, children: recordingChoice === "transcribe"
                                    ? "松开转文字"
                                    : state.status === "transcribing"
                                        ? "正在转写..."
                                        : "松开发送" }), _jsx("div", { style: {
                                    position: "absolute",
                                    bottom: -9,
                                    width: 18,
                                    height: 18,
                                    background: recordingChoice === "transcribe" ? "#E7DCFF" : "#F3EEFF",
                                    transform: "rotate(45deg)",
                                    borderRadius: 3,
                                } })] }), _jsxs("div", { style: {
                            position: "absolute",
                            left: 8,
                            right: 8,
                            bottom: 6,
                            display: "grid",
                            gridTemplateColumns: "1fr 1fr",
                            gap: 14,
                            pointerEvents: "none",
                        }, children: [_jsx("div", { ref: cancelZoneRef, style: {
                                    height: 84,
                                    borderRadius: "46px 46px 24px 24px",
                                    background: recordingChoice === "cancel"
                                        ? "rgba(211, 72, 99, 0.94)"
                                        : "rgba(59, 45, 109, 0.62)",
                                    color: "#FFFFFF",
                                    display: "flex",
                                    alignItems: "center",
                                    justifyContent: "center",
                                    fontSize: 15,
                                    fontWeight: 600,
                                    letterSpacing: "0.02em",
                                    transform: recordingChoice === "cancel" ? "scale(1.03)" : "scale(1)",
                                    transition: `all ${tokens.motion.stateTransition}`,
                                    boxShadow: recordingChoice === "cancel"
                                        ? "0 16px 28px rgba(211, 72, 99, 0.22)"
                                        : "none",
                                }, children: "\u53D6\u6D88" }), _jsx("div", { ref: transcribeZoneRef, style: {
                                    height: 84,
                                    borderRadius: "46px 46px 24px 24px",
                                    background: recordingChoice === "transcribe"
                                        ? "rgba(109, 74, 255, 0.94)"
                                        : "rgba(59, 45, 109, 0.62)",
                                    color: "#FFFFFF",
                                    display: "flex",
                                    alignItems: "center",
                                    justifyContent: "center",
                                    fontSize: 15,
                                    fontWeight: 600,
                                    letterSpacing: "0.02em",
                                    transform: recordingChoice === "transcribe" ? "scale(1.03)" : "scale(1)",
                                    transition: `all ${tokens.motion.stateTransition}`,
                                    boxShadow: recordingChoice === "transcribe"
                                        ? "0 16px 28px rgba(109, 74, 255, 0.24)"
                                        : "none",
                                }, children: "\u8F6C\u6587\u5B57" })] })] })) : null, _jsx(AttachmentPreview, { attachments: attachments.attachments, tokens: tokens }), _jsx("input", { ref: imageInputRef, type: "file", accept: props.image?.accept ?? "image/*", style: { display: "none" }, onChange: (event) => {
                    const file = event.target.files?.[0];
                    if (file) {
                        void handleImageFile(file);
                    }
                    event.currentTarget.value = "";
                } }), _jsxs("div", { style: {
                    position: "relative",
                    display: "grid",
                    gridTemplateColumns: "28px minmax(0, 1fr) auto auto",
                    gap: 4,
                    alignItems: "end",
                    padding: "4px 0 env(safe-area-inset-bottom, 0px)",
                }, children: [_jsx(EmojiPicker, { open: isEmojiOpen, isMobile: true, anchorRef: emojiAnchorRef, onSelect: insertEmoji, onClose: () => setIsEmojiOpen(false) }), _jsx("button", { type: "button", "aria-label": state.mode === "voice" ? "切换到文字输入" : "切换到语音输入", disabled: props.disabled || props.enableVoice === false, onClick: () => {
                            const next = state.mode === "voice" ? "text" : "voice";
                            state.setMode(next);
                            state.setStatus(next === "voice" ? "voice-mode-ready" : "idle");
                        }, style: {
                            display: "inline-flex",
                            alignItems: "center",
                            justifyContent: "center",
                            width: 28,
                            height: 28,
                            border: 0,
                            borderRadius: 999,
                            background: "transparent",
                            color: "#111111",
                            cursor: "pointer",
                            alignSelf: "center",
                            opacity: props.disabled ? 0.45 : 1,
                        }, children: state.mode === "voice" ? _jsx(KeyboardOutlineIcon, { size: 24 }) : _jsx(MicOutlineIcon, { size: 24 }) }), _jsx(InputSurface, { tokens: tokens, status: state.status, styleOverride: {
                            borderRadius: 14,
                            background: "#FFFFFF",
                            borderColor: state.status === "error" ? tokens.color.borderError : "#E5E7EB",
                            boxShadow: "none",
                            minHeight: state.mode === "voice" ? 54 : 44,
                            padding: state.mode === "voice" ? "0" : "0 12px",
                        }, children: state.mode === "voice" ? (_jsx("div", { children: _jsx(HoldToTalkButton, { tokens: tokens, active: isRecordingOverlayVisible, disabled: props.disabled, text: "\u6309\u4F4F \u8BF4\u8BDD", activeText: "\u677E\u5F00 \u53D1\u9001", onPressStart: () => {
                                    setRecordingChoice("send");
                                    voice.startRecording();
                                }, onPressMove: (event) => {
                                    updateRecordingChoice(event.clientX, event.clientY);
                                }, onPressEnd: () => {
                                    if (recordingChoice === "cancel") {
                                        voice.cancelRecording();
                                    }
                                    else if (recordingChoice === "transcribe") {
                                        voice.stopRecording("transcribe");
                                    }
                                    else {
                                        voice.stopRecording("send");
                                    }
                                    setRecordingChoice("send");
                                }, onPressCancel: () => {
                                    setRecordingChoice("send");
                                    voice.cancelRecording();
                                } }) })) : (_jsx(TextComposer, { ref: textComposerRef, tokens: tokens, value: state.text, rows: 1, placeholder: "\u53D1\u6D88\u606F", className: "placeholder:text-[#8A8A8E]", onChange: (event) => {
                                state.setText(event.target.value);
                                state.setStatus(event.target.value.trim() ? "typing" : "idle");
                                props.onChange?.(event.target.value);
                            }, style: {
                                minHeight: 18,
                                paddingTop: 10,
                                paddingBottom: 10,
                                color: "#171717",
                                fontSize: 16,
                                lineHeight: "22px",
                                caretColor: tokens.color.brandPrimary,
                            } })) }), _jsx(EmojiTrigger, { ref: emojiAnchorRef, "data-icon-size": 24, onClick: () => setIsEmojiOpen((prev) => !prev), style: {
                            color: "#111111",
                            alignSelf: "center",
                            width: 28,
                            height: 28,
                        } }), state.mode === "text" && state.text.trim() ? (_jsx(SendAction, { tokens: tokens, disabled: props.disabled, onClick: () => void onSend(), style: {
                            minWidth: 64,
                            minHeight: 30,
                            borderRadius: 12,
                            alignSelf: "center",
                            padding: "0 12px",
                        }, children: "\u53D1\u9001" })) : (_jsx(ImageTrigger, { "data-icon-size": 24, onClick: () => imageInputRef.current?.click(), disabled: props.disabled || isUploadingImage, style: {
                            color: "#111111",
                            alignSelf: "center",
                            width: 28,
                            height: 28,
                            opacity: props.disabled || isUploadingImage ? 0.4 : 1,
                        } }))] }), _jsx(StatusHint, { tokens: tokens, text: state.status === "recording" || state.status === "transcribing" ? undefined : statusText, tone: state.status === "error" ? "error" : "secondary" })] }));
}
export function ChatInputMobile(props) {
    const stateKey = JSON.stringify({
        initialState: props.initialState,
        defaultValue: props.defaultValue,
        voiceModeDefault: props.voiceModeDefault,
    });
    const storeRef = useRef(null);
    if (!storeRef.current || storeRef.current.key !== stateKey) {
        const store = createStore();
        store.set(chatInputModeAtom, props.initialState?.mode ?? props.voiceModeDefault ?? "text");
        store.set(chatInputStatusAtom, props.initialState?.status ?? "idle");
        store.set(chatInputTextAtom, props.initialState?.text ?? props.defaultValue ?? "");
        store.set(chatInputTranscriptAtom, props.initialState?.transcript ?? "");
        store.set(chatInputErrorAtom, props.initialState?.error ?? null);
        store.set(attachmentListAtom, props.initialState?.attachments ?? []);
        store.set(waveformLevelsAtom, props.initialState?.waveformLevels ?? [0.3, 0.5, 0.75, 0.55, 0.35]);
        storeRef.current = { key: stateKey, store };
    }
    return (_jsx(Provider, { store: storeRef.current.store, children: _jsx(MobileInner, { ...props }) }));
}
