import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from "react";
import uuid from "react-uuid";
import { useEditContext } from "../client/editContext";
import { createOrUpdateComment, deleteComment, } from "../services/reviewsService";
import { toast } from "sonner";
import { CommentEditor, COMMENT_INPUT_PLACEHOLDER } from "./CommentEditor";
import { CommentView } from "./CommentView";
import { getCommentParentSnippet } from "./feedbackCommentRules";
function getCurrentReviewId() {
    if (typeof window === "undefined")
        return undefined;
    const reviewId = new URLSearchParams(window.location.search).get("reviewId");
    return reviewId || undefined;
}
function sortByCreated(a, b) {
    return (new Date(a.created || "").getTime() - new Date(b.created || "").getTime());
}
export function groupSuggestionComments(comments) {
    const byId = new Map(comments.map((comment) => [comment.id, comment]));
    const getRootId = (comment) => {
        let current = comment;
        const seen = new Set();
        while (current?.parentCommentId) {
            if (seen.has(current.id))
                break;
            seen.add(current.id);
            const parent = byId.get(current.parentCommentId);
            if (!parent)
                return current.parentCommentId;
            current = parent;
        }
        return current?.id;
    };
    const topLevel = comments
        .filter((comment) => !comment.parentCommentId)
        .sort(sortByCreated);
    const repliesByRootId = new Map();
    comments.forEach((comment) => {
        if (!comment.parentCommentId)
            return;
        const rootId = getRootId(comment);
        if (!rootId)
            return;
        const replies = repliesByRootId.get(rootId) || [];
        replies.push(comment);
        repliesByRootId.set(rootId, replies);
    });
    repliesByRootId.forEach((replies) => replies.sort(sortByCreated));
    return { topLevel, repliesByRootId };
}
export function SuggestionCommentThread({ suggestion, comments, compact = false, constrainHeight = false, resolvedAuthorNames = {}, }) {
    const editContext = useEditContext();
    const [editingCommentId, setEditingCommentId] = React.useState(null);
    const [replyTarget, setReplyTarget] = React.useState(null);
    const [savingKey, setSavingKey] = React.useState(null);
    const { topLevel, repliesByRootId } = React.useMemo(() => groupSuggestionComments(comments), [comments]);
    const canCreate = !editContext?.readonly;
    const buildComment = (text, parentComment) => ({
        id: uuid(),
        isNew: false,
        parentCommentId: parentComment?.id,
        suggestedEditId: suggestion.id,
        itemId: suggestion.itemId,
        itemName: suggestion.itemName,
        mainItemId: suggestion.mainItemId,
        mainItemName: suggestion.mainItemName,
        language: suggestion.mainItemLanguage,
        version: suggestion.mainItemVersion,
        fieldId: suggestion.fieldId,
        text,
        position: 0,
        author: editContext?.user?.name,
        authorDisplayName: editContext?.user?.fullName,
        created: new Date().toISOString(),
    });
    const saveComment = async (text, target, parentComment) => {
        const nextComment = target
            ? { ...target, text }
            : buildComment(text, parentComment);
        const savingId = target?.id || parentComment?.id || suggestion.id;
        setSavingKey(savingId);
        try {
            const result = await createOrUpdateComment(nextComment, getCurrentReviewId());
            if (result.type === "error" || result.type === "unauthorized") {
                console.error("Failed to save suggestion comment:", result);
                toast.error(result.details || result.summary || "Failed to save comment");
                return;
            }
            setEditingCommentId(null);
            setReplyTarget(null);
            await editContext?.loadComments?.();
        }
        catch (error) {
            console.error("Failed to save suggestion comment:", error);
            toast.error(error instanceof Error ? error.message : "Failed to save comment");
        }
        finally {
            setSavingKey(null);
        }
    };
    const deleteTargetComment = async (comment) => {
        try {
            const result = await deleteComment(comment);
            if (result.type === "error" || result.type === "unauthorized") {
                console.error("Failed to delete suggestion comment:", result);
                toast.error(result.details || result.summary || "Failed to delete comment");
                return;
            }
            await editContext?.loadComments?.();
        }
        catch (error) {
            console.error("Failed to delete suggestion comment:", error);
            toast.error(error instanceof Error ? error.message : "Failed to delete comment");
        }
    };
    const handleDelete = (comment) => {
        editContext?.confirm({
            header: "Delete comment",
            message: "Delete this comment? This action cannot be undone.",
            acceptLabel: "Delete",
            showCancel: true,
            accept: () => {
                void deleteTargetComment(comment);
            },
        });
    };
    const renderComment = (comment, rootId) => {
        const isEditing = editingCommentId === comment.id;
        const canEdit = !editContext?.readonly &&
            !comment.isResolved &&
            comment.author === editContext?.user?.name;
        const canDelete = !editContext?.readonly &&
            (comment.author === editContext?.user?.name ||
                editContext?.user?.isAdministrator === true);
        if (isEditing) {
            return (_jsx("div", { className: "mb-3", children: _jsx(CommentEditor, { initialText: comment.text, onSave: (text) => saveComment(text, comment), onCancel: () => setEditingCommentId(null), isSaving: savingKey === comment.id, placeholder: "Edit comment...", submitLabel: "Save", showTagSelector: false, compact: true }) }, comment.id));
        }
        return (_jsx("div", { className: "mb-3", children: _jsx(CommentView, { comment: comment, canEdit: canEdit, canDelete: canDelete, canResolve: false, parentSnippet: getCommentParentSnippet(comment, comments), resolvedAuthorName: comment.author ? resolvedAuthorNames[comment.author] : undefined, onEdit: canEdit ? () => setEditingCommentId(comment.id) : undefined, onDelete: canDelete ? () => handleDelete(comment) : undefined, onReply: canCreate ? () => setReplyTarget({ rootId, comment }) : undefined, showCommentIcon: false, showContextInfo: false, compact: true }) }, comment.id));
    };
    const renderReplyEditor = (root) => {
        if (!replyTarget || replyTarget.rootId !== root.id)
            return null;
        return (_jsxs("div", { className: "mt-3 pt-3", children: [_jsxs("div", { className: "text-neutral-grey-50 mb-2 flex items-center justify-between gap-2 text-xs", children: [_jsxs("span", { className: "truncate", children: ["Replying to", " ", replyTarget.comment.author
                                    ? resolvedAuthorNames[replyTarget.comment.author] ||
                                        replyTarget.comment.authorDisplayName ||
                                        replyTarget.comment.author
                                    : "comment"] }), _jsx("button", { type: "button", className: "badge-pad-sm text-neutral-grey-50 hover:bg-neutral-grey-5 shrink-0 rounded", onClick: () => setReplyTarget(null), children: "Cancel" })] }), _jsx(CommentEditor, { onSave: (text) => saveComment(text, undefined, replyTarget.comment), onCancel: () => setReplyTarget(null), isSaving: savingKey === replyTarget.comment.id, placeholder: COMMENT_INPUT_PLACEHOLDER, submitLabel: "Reply", showTagSelector: false, showCancelButton: false, clearOnSave: true, compact: true }, replyTarget.comment.id)] }));
    };
    const renderRootEditor = () => {
        if (!canCreate || replyTarget)
            return null;
        return (_jsx("div", { className: topLevel.length > 0 ? "mt-3 pt-3" : "", children: _jsx(CommentEditor, { onSave: (text) => saveComment(text), onCancel: () => undefined, isSaving: savingKey === suggestion.id, placeholder: COMMENT_INPUT_PLACEHOLDER, submitLabel: "Reply", showTagSelector: false, showCancelButton: false, clearOnSave: true, compact: true, autoFocus: false }) }));
    };
    if (!canCreate && comments.length === 0)
        return null;
    return (_jsxs("div", { className: compact ? "space-y-3" : "mt-3 pt-3", onClick: (event) => event.stopPropagation(), children: [topLevel.length > 0 && (_jsx("div", { className: compact && constrainHeight ? "max-h-72 overflow-auto pr-1" : "", children: topLevel.map((comment) => {
                    const replies = repliesByRootId.get(comment.id) || [];
                    return (_jsxs("div", { children: [renderComment(comment, comment.id), (replies.length > 0 || replyTarget?.rootId === comment.id) && (_jsxs("div", { className: "border-border-default ml-5 border-l pl-3", children: [replies.map((reply) => renderComment(reply, comment.id)), renderReplyEditor(comment)] }))] }, comment.id));
                }) })), renderRootEditor()] }));
}
//# sourceMappingURL=SuggestionCommentThread.js.map