/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useCallback, useEffect, useRef, useState } from "react";
import { useMessageMutation } from "../../hooks/mutations/useSendMessage";
import { useChatContext } from "../../providers/ChatProvider";
import useChatUIStore from "../../stores/Zustant";
import { FilePreview, FileType } from "../common/FilePreview";
import { MessageStatus } from "../../types/type";
import { Path } from "../../lib/api/endpoint";
import { getChatConfig } from "../../Chat.config";

const MAX_FILE_COUNT = 5;
const ACCEPTED_IMAGE_TYPES = [
  "image/jpeg",
  "image/png",
  "image/gif",
  "image/webp",
  "video/mp4",
  "video/webm",
  "video/ogg",
];
const ACCEPTED_VIDEO_TYPES = ["video/mp4", "video/webm", "video/ogg"];
const ACCEPTED_DOCUMENT_TYPES = [
  "application/pdf",
  "application/msword",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "text/plain",
];

interface Attachment {
  file: File;
  type: FileType;
  previewUrl: string;
  uploadProgress?: number;
  uploadError?: string;
}

const MessageInput = () => {
  // const apiClient = getApiClient();
  const { role, apiClient ,apiUrl} = getChatConfig();
  const { socket, sendMessage, userId } = useChatContext();
  const { selectedConversation, setMessages, setLastSentMessage } = useChatUIStore();

  const [message, setMessage] = useState("");
  const [message1, setMessage1] = useState("");
  const mutation = useMessageMutation();

  const [typingUser, setTypingUser] = useState<string | null>(null);
  const [isSending, setIsSending] = useState(false);
  const [attachments, setAttachments] = useState<Attachment[]>([]);
  const [showAttachmentOptions, setShowAttachmentOptions] = useState(false);

  const fileInputRef = useRef<HTMLInputElement>(null);
  const attachmentsRef = useRef<Attachment[]>([]);
  const [tempMessageId, setTempMessageId] = useState<string | null>(null);
  const [inputError, setInputError] = useState<string | null>(null);
  const attachmentsContainerRef = useRef<HTMLDivElement>(null);
  
  const typingTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const isTypingRef = useRef(false);


  const generateTempId = () =>
    `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  // Join chat room when conversation is selected

  const participantDetails = Array.isArray(
    selectedConversation?.participantDetails
  )
    ? selectedConversation?.participantDetails
    : [selectedConversation?.participantDetails].filter(Boolean);

  const otherParticipant = participantDetails.find(
    (p: any) => p._id !== userId
  );

  // --- Emit typing helpers (debounced / stateful) ---
  const emitTyping = useCallback(() => {
    if (!socket || socket.readyState !== WebSocket.OPEN) return;
    if (!selectedConversation?._id || !otherParticipant?._id) return;

    sendMessage({
      event: "typing",
      data: {
        chatId: selectedConversation._id,
        userId,
        receiverId: otherParticipant._id,
        receiverRole: role === "customer" ? "provider" : "customer",
      },
    });
  }, [socket, selectedConversation?._id, otherParticipant?._id, sendMessage, userId, role]);

  const emitStopTyping = useCallback(() => {
    if (!socket || socket.readyState !== WebSocket.OPEN) return;
    if (!selectedConversation?._id || !otherParticipant?._id) return;

    sendMessage({
      event: "stopTyping",
      data: {
        chatId: selectedConversation._id,
        userId,
        receiverId: otherParticipant._id,
        receiverRole: role === "customer" ? "provider" : "customer",
      },
    });
  }, [socket, selectedConversation?._id, otherParticipant?._id, sendMessage, userId, role]);

  const stopTypingNow = useCallback(() => {
    if (typingTimeoutRef.current) {
      clearTimeout(typingTimeoutRef.current);
      typingTimeoutRef.current = null;
    }
    if (isTypingRef.current) {
      isTypingRef.current = false;
      emitStopTyping();
    }
  }, [emitStopTyping]);


  useEffect(() => {
    if (selectedConversation?._id && socket?.readyState === WebSocket.OPEN) {
      sendMessage({
        event: "joinChat",
        data: {
          chatId: selectedConversation._id,
        },
      });
    }
  }, [selectedConversation?._id, socket, sendMessage]);

  useEffect(() => {
    // Clear all input state when conversation changes
    setMessage("");
    setMessage1("");
    setAttachments([]);
    setInputError(null);
    setShowAttachmentOptions(false);

    stopTypingNow();

    // Clean up any existing file input
    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
  }, [selectedConversation?._id, stopTypingNow]);

  // Typing indicator logic
  // useEffect(() => {
  //   if (!socket || !selectedConversation?._id) return;

  //   if (message.trim() !== "") {
  //     setIsTyping(true);
  //     sendMessage({
  //       event: "typing",
  //       data: {
  //         chatId: selectedConversation._id,
  //         userId,
  //         receiverId: otherParticipant?._id,
  //         receiverRole: role === "customer" ? "provider" : "customer",
  //       },
  //     });
  //   }

  //   typingTimeoutRef.current = setTimeout(() => {
  //     if (message.trim() === "") {
  //       setIsTyping(false);
  //       sendMessage({
  //         event: "stopTyping",
  //         data: {
  //           chatId: selectedConversation._id,
  //           userId,
  //           receiverId: otherParticipant?._id,
  //           receiverRole: role === "customer" ? "provider" : "customer",
  //         },
  //       });
  //     }
  //   }, 200);

  //   return () => {
  //     if (typingTimeoutRef.current) {
  //       clearTimeout(typingTimeoutRef.current);
  //     }
  //   };
  // }, [message, socket, selectedConversation?._id, userId, sendMessage]);

  // // Listen for typing indicators from others
  // useEffect(() => {
  //   if (!socket || !selectedConversation?._id) return;

  //   const handleMessage = (event: MessageEvent) => {
  //     try {
  //       const data = JSON.parse(event.data);
  //       if (
  //         data.event === "typing" &&
  //         data.data.chatId === selectedConversation._id
  //       ) {
  //         setTypingUser(data.data.userId);
  //       } else if (
  //         data.event === "stopTyping" &&
  //         data.data.chatId === selectedConversation._id
  //       ) {
  //         setTypingUser((prev) => (prev === data.data.userId ? null : prev));
  //       }
  //     } catch (error) {
  //       console.error("Error parsing typing message:", error);
  //     }
  //   };

  //   socket.addEventListener("message", handleMessage);
  //   return () => {
  //     socket.removeEventListener("message", handleMessage);
  //   };
  // }, [socket, selectedConversation?._id]);


  // ✅ FIXED Typing indicator logic:
  // - Send "typing" once when user starts typing
  // - Send "stopTyping" after inactivity (even if text remains)
  // - If input becomes empty -> stopTyping once
  useEffect(() => {
    if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);

    const hasText = message.trim().length > 0;

    if (!hasText) {
      // If input empty, ensure stopTyping is emitted once
      if (isTypingRef.current) {
        isTypingRef.current = false;
        emitStopTyping();
      }
      return;
    }

    // Has text
    if (!isTypingRef.current) {
      isTypingRef.current = true;
      emitTyping();
    }

    // If user pauses, stop typing after 1s
    typingTimeoutRef.current = setTimeout(() => {
      if (isTypingRef.current) {
        isTypingRef.current = false;
        emitStopTyping();
      }
    }, 1000);

    return () => {
      if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
    };
  }, [message, emitTyping, emitStopTyping]);

  // Listen for typing indicators from others
  useEffect(() => {
    if (!socket || !selectedConversation?._id) return;

    const handleMessage = (event: MessageEvent) => {
      try {
        const data = JSON.parse(event.data);

        if (data.event === "typing" && data.data.chatId === selectedConversation._id) {
          setTypingUser(data.data.userId);
        } else if (data.event === "stopTyping" && data.data.chatId === selectedConversation._id) {
          setTypingUser((prev) => (prev === data.data.userId ? null : prev));
        }
      } catch (error) {
        console.error("Error parsing typing message:", error);
      }
    };

    socket.addEventListener("message", handleMessage);
    return () => {
      socket.removeEventListener("message", handleMessage);
    };
  }, [socket, selectedConversation?._id]);

  const validateInput = (text: string) => {
    const emailRegex = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i;
    if (emailRegex.test(text)) {
      return "To protect your account, make sure not to share any personal or sensitive information.";
    }

    const phoneRegex =
      /(\+?\d{1,4}[\s-]?)?(\(?\d{3}\)?[\s-]?)?\d{3}[\s-]?\d{4}/;
    if (phoneRegex.test(text)) {
      return "To protect your account, make sure not to share any personal or sensitive information.";
    }

    return null;
  };

  const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const newValue = e.target.value;
    const validationError = validateInput(newValue);

    if (validationError) {
      setInputError(validationError);
      setMessage(newValue);
      setMessage1(newValue);
    } else {
      setInputError(null);
      setMessage(newValue);
      setMessage1(newValue);
    }
  };

  const getFileType = (mimeType: string): FileType | null => {
    if (ACCEPTED_VIDEO_TYPES.includes(mimeType)) return "video";
    if (ACCEPTED_IMAGE_TYPES.includes(mimeType)) return "image";
    if (ACCEPTED_DOCUMENT_TYPES.includes(mimeType)) return "document";
    return null;
  };

  const uploadToS3 = async (
    file: File,
    onProgress?: (progress: number) => void
  ): Promise<{ url: string; name: string; size: number; type: FileType }> => {
    const response = await apiClient.post(`${apiUrl}/${Path.preSignUrl}`, {
      fileName: file.name,
      fileType: file.type,
      conversationId: selectedConversation?._id,
    });

    const { signedUrl, fileUrl } = await response.data;
    const xhr = new XMLHttpRequest();
    xhr.open("PUT", signedUrl, true);
    xhr.setRequestHeader("Content-Type", file.type);

    return new Promise((resolve, reject) => {
      xhr.upload.onprogress = (event) => {
        if (event.lengthComputable && onProgress) {
          const progress = Math.round((event.loaded / event.total) * 100);
          onProgress(progress);
        }
      };

      xhr.onload = () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve({
            url: fileUrl,
            name: file.name,
            size: file.size,
            type: getFileType(file.type),
          });
        } else {
          reject(new Error("Upload failed"));
        }
      };

      xhr.onerror = () => reject(new Error("Upload failed"));
      xhr.send(file);
    });
  };

  //   const otherParticipant = selectedConversation?.participantDetails?.find(
  //   (p:any) => p._id !== userId
  // );

  const handleSubmit = useCallback(
    async (e: React.FormEvent) => {
      e.preventDefault();
      if ((!message.trim() && attachmentsRef.current.length === 0) || isSending)
        return;
      setIsSending(true);
      setAttachments([]);
      setMessage("");
      const tempId = generateTempId();
      setTempMessageId(tempId);

      const optimisticMessage = {
        _id: tempId,
        text: message1,
        message: message1,
        sender: {
          senderId: userId,
          role: role,
        },
        status: "pending" as MessageStatus,
        createdAt: new Date().toISOString(),
        media: attachmentsRef.current.map((att) => ({
          type: att.type,
          url: att.previewUrl,
          name: att.file.name,
          size: att.file.size,
          uploadProgress: 0,
          uploadError: "",
        })),
        isUploading: true,
        isOptimistic: true,
      };

      setMessages((prev) => [...prev, optimisticMessage]);

      try {
        const uploadedFiles = await Promise.all(
          attachmentsRef.current.map(async (attachment, index) => {
            try {
              const result = await uploadToS3(attachment.file, (progress) => {
                setMessages((prev) =>
                  prev.map((msg) => {
                    if (msg._id === tempId) {
                      const updatedMedia = [...msg.media!];
                      updatedMedia[index] = {
                        ...updatedMedia[index],
                        uploadProgress: progress,
                      };
                      return {
                        ...msg,
                        media: updatedMedia,
                      };
                    }
                    return msg;
                  })
                );
              });
              return result;
            } catch (error) {
              console.error(
                `Error uploading file ${attachment.file.name}:`,
                error
              );
              setMessages((prev) =>
                prev.map((msg) => {
                  if (msg._id === tempId) {
                    const updatedMedia = [...msg.media!];
                    updatedMedia[index] = {
                      ...updatedMedia[index],
                      uploadError: "Upload failed",
                    };
                    return {
                      ...msg,
                      media: updatedMedia,
                    };
                  }
                  return msg;
                })
              );
              return null;
            }
          })
        );

        const successfulUploads = uploadedFiles.filter((file) => file !== null);

        if (!otherParticipant?._id) {
          console.error("Cannot send message: receiver ID is missing.");
          setIsSending(false);
          return;
        }

        mutation.mutate(
          {
            receiverId: otherParticipant._id,
            senderId: userId,
            message: message1,
            attachments: successfulUploads,
            bookingId:
              selectedConversation?.type === "service"
                ? selectedConversation?.bookingId
                : undefined,
            serviceTitle:
              selectedConversation?.type === "service"
                ? selectedConversation?.title
                : undefined,
            type: selectedConversation?.type,
            serviceId:
              selectedConversation?.type === "service"
                ? selectedConversation?.serviceId
                : undefined,
            senderRole: role,
            receiverRole: role === "customer" ? "provider" : "customer",
          },
          {
            onSuccess: (data) => {
              const confirmedMessage = data[1];

              setMessages((prev) => {
                const filtered = prev.filter(
                  (msg) => msg._id !== tempMessageId
                );
                return [
                  ...filtered,
                  {
                    ...confirmedMessage,
                    isUploading: false,
                    isOptimistic: false,
                  },
                ];
              });

              // Update the sidebar last message for the sender immediately
              setLastSentMessage({
                _id: confirmedMessage._id,
                conversationId: selectedConversation?._id ?? "",
                message: message1,
                senderId: userId,
                media: successfulUploads,
                status: confirmedMessage.status ?? "sent",
                createdAt: confirmedMessage.createdAt ?? new Date().toISOString(),
                updatedAt: confirmedMessage.updatedAt ?? new Date().toISOString(),
              });

              // Send message via WebSocket
              sendMessage({
                event: "sendMessage",
                data: {
                  chatId: selectedConversation?._id,
                  message: message1,
                  messageId: confirmedMessage._id,
                  attachments: successfulUploads,
                  senderId: userId,
                  receiverId: otherParticipant._id,
                  receiverRole: role === "customer" ? "provider" : "customer",
                  senderRole: role,
                },
              });
            },
            onError: (error) => {
              console.error("Error in sending message:", error);
              setMessages((prev) =>
                prev.map((msg) =>
                  msg._id === tempId ? { ...msg, status: "failed" } : msg
                )
              );
            },
          }
        );
      } catch (error) {
        console.error("Error sending message:", error);
        setMessages((prev) =>
          prev.map((msg) =>
            msg._id === tempId ? { ...msg, status: "failed" } : msg
          )
        );
      } finally {
        setIsSending(false);
        setMessage1("");
        setAttachments([]);
        setTempMessageId(null);
      }
    },
    [
      message,
      message1,
      selectedConversation,
      userId,
      isSending,
      mutation,
      setMessages,
      sendMessage,
    ]
  );

  // Clean up object URLs when component unmounts
  useEffect(() => {
    return () => {
      attachments.forEach((attachment) => {
        URL.revokeObjectURL(attachment.previewUrl);
      });
    };
  }, [attachments]);

  // Update attachments ref
  useEffect(() => {
    attachmentsRef.current = attachments;
  }, [attachments]);

  {/* File attachment handlers */}

  // File attachment handlers
  const handleAttachmentClick = () => {
    setShowAttachmentOptions(!showAttachmentOptions);
  };

  const handleFileSelect = (type: FileType) => {
    if (fileInputRef.current) {
      fileInputRef.current.accept = getAcceptString(type);
      fileInputRef.current.click();
    }
    setShowAttachmentOptions(false);
  };

  const getAcceptString = (type: FileType): string => {
    switch (type) {
      case "image":
        return ACCEPTED_IMAGE_TYPES.join(",");
      case "video":
        return ACCEPTED_VIDEO_TYPES.join(",");
      case "document":
        return ACCEPTED_DOCUMENT_TYPES.join(",");
      default:
        return "*";
    }
  };

  const FILE_SIZE_LIMITS_MB = {
    image: 10,
    video: 120,
    document: 10,
  } as const;

  const getMaxSizeForType = (type: Attachment["type"] | null) => {
    if (!type) return 0;
    return FILE_SIZE_LIMITS_MB[type] * 1024 * 1024;
  };

  // const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
  //   const files = e.target.files;
  //   if (!files || files.length === 0) return;

  //   if (attachments.length + files.length > MAX_FILE_COUNT) {
  //     alert(`You can only attach up to ${MAX_FILE_COUNT} files`);
  //     return;
  //   }

  //   const newFilesSize = Array.from(files).reduce(
  //     (total, file) => total + file.size,
  //     0
  //   );
  //   const currentAttachmentsSize = attachments.reduce(
  //     (total, att) => total + att.file.size,
  //     0
  //   );

  //   if (
  //     currentAttachmentsSize + newFilesSize >
  //     MAX_FILE_SIZE_MB * 1024 * 1024
  //   ) {
  //     alert(`Total file size cannot exceed ${MAX_FILE_SIZE_MB}MB`);
  //     return;
  //   }

  //   const newAttachments: Attachment[] = [];

  //   for (let i = 0; i < files.length; i++) {
  //     const file = files[i];
  //     const fileType = getFileType(file.type);

  //     if (!fileType) {
  //       console.error(`Unsupported file type: ${file.type}`);
  //       continue;
  //     }

  //     if (file.size > MAX_FILE_SIZE_MB * 1024 * 1024) {
  //       console.error(`File too large: ${file.name}`);
  //       continue;
  //     }

  //     const previewUrl =
  //       fileType === "document"
  //         ? URL.createObjectURL(new Blob([""], { type: "application/pdf" }))
  //         : URL.createObjectURL(file);

  //     newAttachments.push({
  //       file,
  //       type: fileType,
  //       previewUrl,
  //     });
  //   }

  //   setAttachments((prev) => [...prev, ...newAttachments]);
  //   if (fileInputRef.current) {
  //     fileInputRef.current.value = "";
  //   }
  // };

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    setInputError(null);
    const files = e.target.files;
    if (!files || files.length === 0) return;

    const newAttachments: Attachment[] = [];

    if (attachments.length + files.length > MAX_FILE_COUNT) {
      return setInputError(`You can only attach up to ${MAX_FILE_COUNT} files`); // toast / inline message
    }

    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      const fileType = getFileType(file.type);

      if (!fileType) {
        setInputError(`Unsupported file: ${file.name}`);
        continue;
      }

      const maxSize = getMaxSizeForType(fileType);

      if (file.size > maxSize) {
        setInputError(
          `${file.name} exceeds ${FILE_SIZE_LIMITS_MB[fileType]}MB limit`
        );
        continue;
      }

      const previewUrl =
        fileType === "document"
          ? URL.createObjectURL(new Blob([""], { type: "application/pdf" }))
          : URL.createObjectURL(file);

      newAttachments.push({
        file,
        type: fileType,
        previewUrl,
      });
    }

    if (newAttachments.length) {
      setAttachments((prev) => [...prev, ...newAttachments]);
      setInputError(null); 
    }

    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
  };

  const scrollAttachments = (direction: "left" | "right") => {
    if (attachmentsContainerRef.current) {
      const scrollAmount = direction === "right" ? 200 : -200;
      attachmentsContainerRef.current.scrollBy({
        left: scrollAmount,
        behavior: "smooth",
      });
    }
  };

  const removeAttachment = (index: number) => {
    setInputError(null); 
    setAttachments((prev) => {
      const newAttachments = [...prev];
      URL.revokeObjectURL(newAttachments[index].previewUrl);
      newAttachments.splice(index, 1);
      return newAttachments;
    });
  };

  {/* end of file attachment handlers */}

  return (
    <div className="message-input-container">
      {attachments.length > 0 && (
        <div className="attachments-preview-container">
          <button
            className="scroll-button left"
            onClick={() => scrollAttachments("left")}
            disabled={attachments.length <= 3}
          >
            &lt;
          </button>

          <div className="attachments-preview" ref={attachmentsContainerRef}>
            {attachments.map((attachment, index) => (
              <FilePreview
                key={index}
                file={attachment.file}
                type={attachment.type}
                previewUrl={attachment.previewUrl}
                onRemove={() => removeAttachment(index)}
              />
            ))}

            {attachments.length < MAX_FILE_COUNT && (
              <div
                className="add-more-files"
                onClick={() => fileInputRef.current?.click()}
              >
                <div className="plus-icon">+</div>
                <div className="add-more-text">Add more</div>
              </div>
            )}
          </div>

          <button
            className="scroll-button right"
            onClick={() => scrollAttachments("right")}
            disabled={attachments.length <= 3}
          >
            &gt;
          </button>
        </div>
      )}

      <form className="chatMessageInputform" onSubmit={handleSubmit}>
        {inputError && (
          <p style={{ color: "red", fontSize: "12px" }}>{inputError}</p>
        )}

        <div className="chatMessageInputdiv">
          <input
            type="file"
            ref={fileInputRef}
            style={{ display: "none" }}
            onChange={handleFileChange}
            multiple
          />

          <div className="attachment-container">
            <button
              type="button"
              className="attachment-button"
              aria-label="Add attachment"
              onClick={handleAttachmentClick}
            >
              <div className="attachment-icon">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="15"
                  height="15"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
                </svg>
              </div>
            </button>

            {showAttachmentOptions && (
              <div className="attachment-options">
                <button type="button" onClick={() => handleFileSelect("image")}>
                  <div className="icon">
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="18"
                      height="18"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      strokeWidth="2"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                    >
                      <rect
                        x="3"
                        y="3"
                        width="18"
                        height="18"
                        rx="2"
                        ry="2"
                      ></rect>
                      <circle cx="8.5" cy="8.5" r="1.5"></circle>
                      <polyline points="21 15 16 10 5 21"></polyline>
                    </svg>
                  </div>
                  <span>Photos & videos</span>
                </button>
                <button
                  type="button"
                  onClick={() => handleFileSelect("document")}
                >
                  <div className="icon">
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="18"
                      height="18"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      strokeWidth="2"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                    >
                      <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                      <polyline points="14 2 14 8 20 8"></polyline>
                      <line x1="16" y1="13" x2="8" y2="13"></line>
                      <line x1="16" y1="17" x2="8" y2="17"></line>
                      <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                  </div>
                  <span>Document</span>
                </button>
              </div>
            )}
          </div>

          <textarea
            className="chatMessageInput"
            placeholder="Send a message"
            value={message}
            onChange={handleChange}
            rows={1}
            style={{ resize: "none" }}
            onKeyDown={(e) => {
              if (e.key === "Enter" && !e.shiftKey) {
                e.preventDefault();
                handleSubmit(e);
              }
            }}
          />

          <button
            type="submit"
            className="chatMessageInputSubmit"
            aria-label="Send message"
            disabled={!!inputError || isSending}
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              className="icon"
              width="13"
              height="13"
              viewBox="0 0 24 24"
              fill="#ffffff"
              aria-hidden="true"
            >
              <path d="M3 11.5 21 3l-8.5 18-2.2-7.3z" />
            </svg>
          </button>
        </div>

        {typingUser &&
          typingUser !== userId &&
          typingUser === otherParticipant?._id &&
          !isSending && (
            <div className="typing-indicator" aria-live="polite">
              <span className="typing-indicator__pill">
                <span className="typing-indicator__dot" />
                <span className="typing-indicator__dot" />
                <span className="typing-indicator__dot" />
              </span>
            </div>
          )}
      </form>
    </div>
  );
};

export default MessageInput;
