import React, { useEffect, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import { KebabIcon } from "../../../icons/ExportCommonIcons";
import { adjustHeight } from "../function/textAreaHeightAdjust";
import { useSocketStore } from "../../../../store/socket/useSocketStore";
import { useSelectedComment } from "../../../../store/builder/store";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { getAvatarColor } from "../../../../modules/collaboration/functions/getAvatarColor";
import { getUserData } from "../../../../functions/getUserData";
import { getRelativeTime } from "../function/getRelativeTime";

import { editThreadTitleApi } from "../../../../services/factoryBuilder/collab/comments/editThreadTitleApi";
import { deleteCommentApi } from "../../../../services/factoryBuilder/collab/comments/deleteCommentApi";
import { editCommentsApi } from "../../../../services/factoryBuilder/collab/comments/editCommentApi";

interface MessageProps {
    val: Reply | ThreadSchema;
    i: number;
    setMessages?: React.Dispatch<React.SetStateAction<Reply[]>>;
    setIsEditable?: React.Dispatch<React.SetStateAction<boolean>>;
    setEditedThread?: React.Dispatch<React.SetStateAction<boolean>>;
    setMode?: React.Dispatch<React.SetStateAction<"create" | "edit" | null>>;
    isEditable?: boolean;
    isEditableThread?: boolean;
    editedThread?: boolean;
    mode?: "create" | "edit" | null;
}

const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEditable, setEditedThread, editedThread, isEditableThread, setMode }) => {
    const [openOptions, setOpenOptions] = useState(false);
    const { projectId } = useParams();
    const { threadSocket } = useSocketStore();
    const { userName, userId, organization } = getUserData();
    const [isEditComment, setIsEditComment] = useState(false);
    const { selectedComment, setCommentPositionState } = useSelectedComment();
    const { versionStore, threadStore } = useSceneContext();
    const { updateThread, removeReply, updateReply } = threadStore();
    const { selectedVersion } = versionStore();

    const [value, setValue] = useState<string>("comment" in val ? val.comment : val.threadTitle);

    const textareaRef = useRef<HTMLTextAreaElement>(null);

    useEffect(() => {
        if (textareaRef.current) adjustHeight(textareaRef.current);
    }, [value]);

    function handleCancelAction() {
        setCommentPositionState(null);
        if (setIsEditable) setIsEditable(true);
        setIsEditComment(false);
    }

    const handleSaveAction = async () => {
        if (!projectId || !selectedVersion) return;

        if (isEditableThread && editedThread) {
            if (!threadSocket?.active) {
                // API

                editThreadTitleApi(projectId, (val as ThreadSchema).threadId, value, selectedVersion?.versionId || "").then((editThreadTitle) => {
                    if (editThreadTitle.message == "ThreadTitle updated Successfully") {
                        const editedThread: ThreadSchema = {
                            state: "active",
                            threadId: editThreadTitle.data.replyId,
                            creatorId: userId,
                            createdAt: getRelativeTime(editThreadTitle.data.createdAt),
                            threadTitle: value,
                            lastUpdatedAt: new Date().toISOString(),
                            position: editThreadTitle.data.position,
                            rotation: [0, 0, 0],
                            comments: [],
                        };
                        updateThread((val as ThreadSchema).threadId, editedThread);
                    }
                });
            } else {
                // SOCKET

                const threadEdit = {
                    projectId,
                    userId,
                    threadTitle: value,
                    organization,
                    threadId: (val as ThreadSchema).threadId || selectedComment.threadId,
                    versionId: selectedVersion?.versionId || "",
                };

                threadSocket.emit("v1:thread:updateTitle", threadEdit);
            }
        } else if (mode === "edit") {
            if (!threadSocket?.active) {
                // API

                editCommentsApi(projectId, value, selectedComment?.threadId, (val as Reply).replyId, selectedVersion?.versionId || "").then((editComments) => {
                    const commentData = {
                        replyId: `${editComments.data?.replyId}`,
                        creatorId: `${userId}`,
                        createdAt: getRelativeTime(editComments.data?.createdAt),
                        lastUpdatedAt: "2 hrs ago",
                        comment: value,
                    };

                    updateReply((val as ThreadSchema).threadId, (val as Reply)?.replyId, commentData);

                    if (setIsEditable) setIsEditable(true);
                    if (setEditedThread) setEditedThread(false);
                });
            } else {
                // SOCKET

                const editComment = {
                    projectId,
                    userId,
                    comment: value,
                    organization,
                    threadId: selectedComment?.threadId,
                    commentId: (val as Reply).replyId ?? "",
                    versionId: selectedVersion?.versionId || "",
                };

                threadSocket.emit("v1-Comment:add", editComment);
                if (setIsEditable) setIsEditable(true);
                if (setEditedThread) setEditedThread(false);
            }
        }
        setIsEditComment(false);
    };

    const handleDeleteAction = async (replyID: any) => {
        if (!projectId || !selectedVersion || !setMessages) return;
        setOpenOptions(false);

        if (!threadSocket?.active) {
            // API

            deleteCommentApi(projectId, selectedComment?.threadId, (val as Reply).replyId, selectedVersion?.versionId || "").then((deletedComment) => {
                if (deletedComment === "'Thread comment deleted Successfully'") {
                    setMessages((prev) => prev.filter((message) => message.replyId !== replyID));
                    removeReply(val.creatorId, replyID);
                }
            });
        } else {
            // SOCKET

            const deleteComment = {
                projectId,
                userId,
                commentId: (val as Reply).replyId,
                organization,
                threadId: selectedComment?.threadId,
                versionId: selectedVersion?.versionId || "",
            };
            setMessages((prev) => {
                return prev.filter((message) => message.replyId !== (val as Reply).replyId);
            });
            removeReply(selectedComment?.threadId, (val as Reply).replyId);

            threadSocket.emit("v1-Comment:delete", deleteComment);
        }
    };

    const handleFocus = (e: React.FocusEvent<HTMLTextAreaElement>) => {
        requestAnimationFrame(() => {
            if (textareaRef.current) {
                const length = textareaRef.current.value.length;
                textareaRef.current.setSelectionRange(length, length);
            }
        });
    };

    return (
        <>
            {isEditComment ? (
                <div className="edit-container">
                    <div className="input-container">
                        <textarea placeholder="type here" ref={textareaRef} autoFocus value={value} onChange={(e) => setValue(e.target.value)} style={{ resize: "none" }} onFocus={handleFocus} />
                    </div>
                    <div className="actions-container">
                        <div className="options"></div>
                        <div className="actions">
                            <button
                                className="cancel-button"
                                onClick={() => {
                                    handleCancelAction();
                                }}
                            >
                                Cancel
                            </button>
                            <button
                                className="save-button"
                                onClick={() => {
                                    handleSaveAction();
                                }}
                            >
                                Save
                            </button>
                        </div>
                    </div>
                </div>
            ) : (
                <div className="message-container">
                    <div className="profile" style={{ background: getAvatarColor(i, userId) }}>
                        {userName?.charAt(0).toUpperCase() || "user"}
                    </div>
                    <div className="content">
                        <div className="user-details">
                            <div className="user-name">{userName}</div>
                            <div className="time">{isEditableThread ? getRelativeTime(val.createdAt) : val.createdAt}</div>
                        </div>
                        {(val as Reply).creatorId === userId && (
                            <div className="more-options" onMouseLeave={() => setOpenOptions(false)}>
                                <button
                                    className="more-options-button"
                                    onClick={() => {
                                        setOpenOptions(!openOptions);
                                    }}
                                >
                                    <KebabIcon />
                                </button>

                                {openOptions && (
                                    <div className="options-list">
                                        <button
                                            className="option"
                                            onClick={(e) => {
                                                e.preventDefault();
                                                setMode && setMode("edit");
                                                setOpenOptions(false);
                                                setEditedThread && setEditedThread(true);
                                                setIsEditComment(true);
                                            }}
                                        >
                                            Edit
                                        </button>

                                        {!isEditableThread && (
                                            <button
                                                className="option"
                                                onClick={() => {
                                                    handleDeleteAction((val as Reply).replyId);
                                                }}
                                            >
                                                Delete
                                            </button>
                                        )}
                                    </div>
                                )}
                            </div>
                        )}

                        <div className="message">{"comment" in val ? val.comment : val.threadTitle}</div>
                    </div>
                </div>
            )}
        </>
    );
};

export default Messages;
