import { useMemo } from 'react';
import type { Comment } from '@eigenpal/docx-editor-core/types/content';
import type { ReactSidebarItem } from '../plugin-api/types';
import type { TrackedChangeEntry } from '../components/sidebar/cardUtils';
import { CommentCard } from '../components/sidebar/CommentCard';
import { TrackedChangeCard } from '../components/sidebar/TrackedChangeCard';
import { AddCommentCard } from '../components/sidebar/AddCommentCard';
import { ResolvedCommentMarker } from '../components/sidebar/ResolvedCommentMarker';

export interface CommentCallbacks {
  onCommentReply?: (commentId: number, text: string) => void;
  onCommentResolve?: (commentId: number) => void;
  onCommentUnresolve?: (commentId: number) => void;
  onCommentDelete?: (commentId: number) => void;
  onAddComment?: (text: string) => void;
  onCancelAddComment?: () => void;
  onAcceptChange?: (from: number, to: number) => void;
  onRejectChange?: (from: number, to: number) => void;
  /**
   * Accept a structural revision (e.g. `pPrIns`/`pPrDel`) by its `w:id`.
   * Required for entries whose `type` is `paragraphMarkInsertion` or
   * `paragraphMarkDeletion`; ignored by inline-entry cards.
   */
  onAcceptChangeById?: (revisionId: number) => void;
  /** See `onAcceptChangeById`. */
  onRejectChangeById?: (revisionId: number) => void;
  onTrackedChangeReply?: (revisionId: number, text: string) => void;
}

export interface UseCommentSidebarItemsProps {
  comments: Comment[];
  trackedChanges: TrackedChangeEntry[];
  callbacks: CommentCallbacks;
  /** When sidebar is open, include resolved comments */
  showResolved?: boolean;
  isAddingComment?: boolean;
  addCommentYPosition?: number | null;
}

export function useCommentSidebarItems({
  comments,
  trackedChanges,
  callbacks,
  showResolved = false,
  isAddingComment = false,
  addCommentYPosition = null,
}: UseCommentSidebarItemsProps): ReactSidebarItem[] {
  // Active comments always, resolved only when showResolved
  const visibleComments = useMemo(
    () =>
      comments.filter((c) => {
        if (c.parentId != null) return false;
        if (c.done && !showResolved) return false;
        return true;
      }),
    [comments, showResolved]
  );

  // Pre-group replies by parentId
  const repliesByParent = useMemo(() => {
    const map = new Map<number, Comment[]>();
    for (const c of comments) {
      if (c.parentId != null) {
        const arr = map.get(c.parentId);
        if (arr) arr.push(c);
        else map.set(c.parentId, [c]);
      }
    }
    return map;
  }, [comments]);

  return useMemo(() => {
    const items: ReactSidebarItem[] = [];

    // "Add comment" input (temporary item with pre-computed Y)
    if (isAddingComment && addCommentYPosition != null) {
      items.push({
        id: 'new-comment-input',
        anchorPos: 0,
        fixedY: addCommentYPosition,
        priority: -1000, // always first at its Y
        isTemporary: true,
        estimatedHeight: 120,
        render: (props) => (
          <AddCommentCard
            {...props}
            onSubmit={callbacks.onAddComment}
            onCancel={callbacks.onCancelAddComment}
          />
        ),
      });
    }

    // Comment cards — resolved render as icon when collapsed, full card when expanded
    for (const comment of visibleComments) {
      const replies = repliesByParent.get(comment.id) ?? [];
      items.push({
        id: `comment-${comment.id}`,
        anchorPos: 0,
        anchorKey: `comment-${comment.id}`,
        priority: 0,
        estimatedHeight: comment.done ? 28 : 80,
        render: (props) =>
          comment.done && !props.isExpanded ? (
            <ResolvedCommentMarker {...props} comment={comment} />
          ) : (
            <CommentCard
              {...props}
              comment={comment}
              replies={replies}
              onReply={callbacks.onCommentReply}
              onResolve={callbacks.onCommentResolve}
              onUnresolve={callbacks.onCommentUnresolve}
              onDelete={callbacks.onCommentDelete}
            />
          ),
      });
    }

    // Tracked change cards
    trackedChanges.forEach((change, idx) => {
      const replies = repliesByParent.get(change.revisionId) ?? [];
      items.push({
        id: `tc-${change.revisionId}-${idx}`,
        anchorPos: change.from,
        anchorKey: `revision-${change.revisionId}`,
        priority: 1,
        estimatedHeight: 80,
        render: (props) => (
          <TrackedChangeCard
            {...props}
            change={change}
            replies={replies}
            onAccept={callbacks.onAcceptChange}
            onReject={callbacks.onRejectChange}
            onAcceptById={callbacks.onAcceptChangeById}
            onRejectById={callbacks.onRejectChangeById}
            onReply={callbacks.onTrackedChangeReply}
          />
        ),
      });
    });

    return items;
  }, [
    visibleComments,
    trackedChanges,
    repliesByParent,
    callbacks,
    isAddingComment,
    addCommentYPosition,
  ]);
}
