import React, { useEffect, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import { CloseIcon, KebabIcon } from "../../../icons/ExportCommonIcons";
import { ExpandIcon } from "../../../icons/SimulationIcons";
import { adjustHeight } from "../function/textAreaHeightAdjust";
import { useSelectedComment } from "../../../../store/builder/store";
import { useSocketStore } from "../../../../store/socket/useSocketStore";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import Messages from "./Messages";
import ThreadSocketResponsesDev from "../../../../modules/collaboration/socket/threadSocketResponses.dev";

import { getUserData } from "../../../../functions/getUserData";
import { addCommentsApi } from "../../../../services/factoryBuilder/collab/comments/addCommentApi";
import { deleteThreadApi } from "../../../../services/factoryBuilder/collab/comments/deleteThreadApi";
import { createThreadApi } from "../../../../services/factoryBuilder/collab/comments/createThreadApi";
import { getRelativeTime } from "../function/getRelativeTime";

const ThreadChat: React.FC = () => {
    const { userId, organization } = getUserData();
    const [openThreadOptions, setOpenThreadOptions] = useState(false);
    const [inputActive, setInputActive] = useState(false);
    const [value, setValue] = useState<string>("");
    const { selectedComment, setSelectedComment, setCommentPositionState, commentPositionState, position2Dstate } = useSelectedComment();
    const [mode, setMode] = useState<"create" | "edit" | null>("create");
    const [isEditable, setIsEditable] = useState(false);
    const [editedThread, setEditedThread] = useState(false);
    const textareaRef = useRef<HTMLTextAreaElement>(null);
    const wrapperRef = useRef<HTMLDivElement>(null);
    const [messages, setMessages] = useState<Reply[]>([]);
    const { projectId } = useParams();
    const [dragging, setDragging] = useState(false);
    const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
    const [position, setPosition] = useState({ x: position2Dstate.x, y: position2Dstate.y });
    const { threadSocket } = useSocketStore();
    const modeRef = useRef<"create" | "edit" | null>(null);
    const messagesRef = useRef<HTMLDivElement>(null);
    const { versionStore, threadStore } = useSceneContext();
    const { selectedVersion } = versionStore();
    const { addThread, removeThread, addReply, threads } = threadStore();

    useEffect(() => {
        modeRef.current = mode;
    }, [mode]);

    useEffect(() => {
        if (threads.length > 0 && selectedComment) {
            const allMessages = threads
                .flatMap((val: any) => (val?.threadId === selectedComment?.threadId ? val.comments : []))
                .map((c) => {
                    return {
                        replyId: c._id ?? c.replyId,
                        creatorId: c.creatorId || c.userId,
                        createdAt: c.createdAt,
                        lastUpdatedAt: "1 hr ago",
                        comment: c.comment,
                        _id: c._id ?? c.replyId,
                    };
                });

            setMessages(allMessages);
        }
    }, [selectedComment]);

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

    const clamp = (val: number, min: number, max: number) => {
        return Math.min(Math.max(val, min), max);
    };

    const handlePointerDown = (event: React.PointerEvent<HTMLDivElement>) => {
        if (event.button !== 0) return;
        const target = event.target as HTMLElement;
        if (
            target.closest("button") ||
            target.closest(".sent-button") ||
            target.closest("textarea") ||
            target.closest(".options-button") ||
            target.closest(".options-list") ||
            target.closest(".send-message-wrapper") ||
            target.closest(".options delete")
        ) {
            return;
        }

        const wrapper = wrapperRef.current;
        if (!wrapper) return;

        const rect = wrapper.getBoundingClientRect();
        const offsetX = event.clientX - rect.left;
        const offsetY = event.clientY - rect.top;

        setDragging(true);
        setDragOffset({ x: offsetX, y: offsetY });

        wrapper.setPointerCapture(event.pointerId);
    };

    const updatePosition = ({ clientX, clientY }: { clientX: number; clientY: number }, allowMove: boolean = true) => {
        if (!allowMove || !wrapperRef.current) return;

        const container = document.getElementById("work-space-three-d-canvas");
        const wrapper = wrapperRef.current;
        if (!container || !wrapper) return;

        const containerRect = container.getBoundingClientRect();

        let newX = clientX - containerRect.left - dragOffset.x;
        let newY = clientY - containerRect.top - dragOffset.y;

        const maxX = containerRect.width - wrapper.offsetWidth;
        const maxY = containerRect.height - wrapper.offsetHeight;

        newX = clamp(newX, 0, maxX);
        newY = clamp(newY, 0, maxY);

        setPosition({ x: newX, y: newY });
    };

    const handlePointerMove = (e: { clientX: number; clientY: number }) => {
        if (dragging) updatePosition(e, true);
    };

    // Commented this useEffect to prevent offset after user saved the comment
    // useEffect(() => {
    //   updatePosition({ clientX: position.x, clientY: position.y }, true);
    // }, [selectedComment]);

    const handlePointerUp = (event: React.PointerEvent<HTMLDivElement>) => {
        if (!dragging) return;
        setDragging(false);
        const wrapper = wrapperRef.current;
        if (wrapper) wrapper.releasePointerCapture(event.pointerId);
    };

    const handleCreateComments = async (e: any) => {
        e.preventDefault();
        if (!value) return;

        if (!threadSocket?.connected && mode === "create") {
            // API

            addCommentsApi(projectId, value, selectedComment?.threadId, selectedVersion?.versionId || "").then((createComments) => {
                if (createComments.message === "Thread comments add Successfully" && createComments.data) {
                    const commentData = {
                        replyId: `${createComments.data?._id}`,
                        creatorId: `${selectedComment?.threadId}`,
                        createdAt: "2 hrs ago",
                        lastUpdatedAt: "2 hrs ago",
                        comment: value,
                    };
                    setMessages((prevMessages) => [...prevMessages, commentData]);
                    addReply(selectedComment?.threadId, commentData);
                }
            });
        } else if (threadSocket?.connected && mode === "create") {
            // SOCKET

            const addThread = {
                versionId: selectedVersion?.versionId || "",
                projectId,
                userId,
                comment: value,
                organization,
                threadId: selectedComment?.threadId,
            };

            threadSocket.emit("v1-Comment:add", addThread);
        }
        setInputActive(false);
    };

    const handleDeleteThread = async () => {
        if (!projectId) return;

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

            deleteThreadApi(projectId, selectedComment?.threadId, selectedVersion?.versionId || "").then((deleteThread) => {
                if (deleteThread.message === "Thread deleted Successfully") {
                    removeThread(selectedComment?.threadId);
                    setSelectedComment(null);
                }
            });
        } else {
            // SOCKET

            const deleteThread = {
                projectId,
                userId,
                organization,
                threadId: selectedComment?.threadId,
                versionId: selectedVersion?.versionId || "",
            };
            setSelectedComment(null);
            removeThread(selectedComment?.threadId);
            threadSocket.emit("v1:thread:delete", deleteThread);
        }
    };

    const handleCreateThread = async (e: any) => {
        e.preventDefault();
        if (!projectId) return;

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

            createThreadApi(projectId, "active", commentPositionState.position, [0, 0, 0], value, selectedVersion?.versionId || "").then((thread) => {
                if (thread.message === "Thread created Successfully" && thread?.threadData) {
                    const comment: ThreadSchema = {
                        state: "active",
                        threadId: thread?.threadData?._id,
                        creatorId: userId,
                        createdAt: getRelativeTime(thread.threadData?.createdAt),
                        threadTitle: value,
                        lastUpdatedAt: new Date().toISOString(),
                        position: commentPositionState.position,
                        rotation: [0, 0, 0],
                        comments: [],
                    };
                    addThread(comment);
                    setCommentPositionState(null);
                    setInputActive(false);
                    setSelectedComment(null);
                }
            });
        } else {
            // SOCKET

            const createThread = {
                projectId,
                versionId: selectedVersion?.versionId || "",
                userId,
                organization,
                state: "active",
                position: commentPositionState.position,
                rotation: [0, 0, 0],
                threadTitle: value,
            };

            setCommentPositionState(null);
            setInputActive(false);
            setSelectedComment(null);
            threadSocket.emit("v1:thread:create", createThread);
        }
    };

    const scrollToBottom = () => {
        const messagesWrapper = document.querySelector(".messages-wrapper");
        if (messagesWrapper) {
            messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
        }
    };

    useEffect(() => {
        if (messages.length > 0) scrollToBottom();
    }, [messages]);

    return (
        <div
            ref={wrapperRef}
            className="thread-chat-wrapper"
            onPointerDown={handlePointerDown}
            onPointerMove={(e) => handlePointerMove({ clientX: e.clientX, clientY: e.clientY })}
            onPointerUp={handlePointerUp}
            style={{
                position: "absolute",
                left: position.x,
                top: position.y,
                cursor: dragging ? "grabbing" : "grab",
                userSelect: "none",
                zIndex: 9999,
            }}
        >
            <div className="thread-chat-container">
                <div className="header-wrapper">
                    <div className="header">Comment</div>
                    <div className="header-options">
                        <div
                            className="options-button"
                            style={{ cursor: "pointer" }}
                            onClick={(e) => {
                                e.preventDefault();
                                setOpenThreadOptions((prev) => !prev);
                            }}
                        >
                            <KebabIcon />
                        </div>
                        {openThreadOptions && (
                            <div className="options-list">
                                <div className="options">Mark as Unread</div>
                                <div className="options">Mark as Resolved</div>
                                <div className="options delete" onClick={handleDeleteThread}>
                                    Delete Thread
                                </div>
                            </div>
                        )}
                        <button
                            className="close-button"
                            onClick={() => {
                                setSelectedComment(null);
                                setCommentPositionState(null);
                            }}
                        >
                            <CloseIcon />
                        </button>
                    </div>
                </div>

                <div className="messages-wrapper" ref={messagesRef}>
                    {selectedComment && <Messages val={selectedComment} i={1} key={selectedComment.creatorId} isEditableThread={true} setEditedThread={setEditedThread} editedThread={editedThread} />}
                    {messages.map((val, i) => (
                        <Messages
                            val={val as any}
                            i={i}
                            key={val.replyId}
                            setMessages={setMessages}
                            setIsEditable={setIsEditable}
                            isEditable={isEditable}
                            isEditableThread={false}
                            setMode={setMode}
                            mode={mode}
                        />
                    ))}
                </div>

                <div className="send-message-wrapper">
                    <div className={`input-container ${inputActive ? "active" : ""}`}>
                        <textarea
                            placeholder={commentPositionState && selectedComment === null ? "Type Thread Title" : "type something"}
                            ref={textareaRef}
                            value={value}
                            onChange={(e) => setValue(e.target.value)}
                            onKeyDown={(e) => {
                                if (e.key === "Enter") {
                                    e.preventDefault();
                                    if (commentPositionState && selectedComment === null) {
                                        handleCreateThread(e);
                                    } else {
                                        setMode("create");
                                        handleCreateComments(e);
                                        textareaRef.current?.blur();
                                    }
                                    setValue("");
                                }
                                if (e.key === "Escape") {
                                    textareaRef.current?.blur();
                                }
                            }}
                            onClick={() => {
                                if (!commentPositionState && selectedComment !== null) {
                                    setMode("create");
                                }
                            }}
                            autoFocus={selectedComment === null}
                            onBlur={() => setInputActive(false)}
                            onFocus={() => setInputActive(true)}
                            style={{ resize: "none" }}
                        />
                        <div
                            className={`sent-button ${value === "" ? "disable-send-btn" : ""}`}
                            onClick={(e) => {
                                if (commentPositionState && selectedComment === null) {
                                    handleCreateThread(e);
                                } else {
                                    setMode("create");
                                    handleCreateComments(e);
                                }
                                setValue("");
                            }}
                        >
                            <ExpandIcon />
                        </div>
                    </div>
                </div>
            </div>
            <ThreadSocketResponsesDev setMessages={setMessages} modeRef={modeRef} messages={messages} />
        </div>
    );
};

export default ThreadChat;
