import {
  useRedaction as useEmbedPdfRedaction,
  RedactionSelectionMenuProps,
} from "@embedpdf/plugin-redaction/react";
import { PdfAnnotationSubtype } from "@embedpdf/models";
import { ActionIcon, Tooltip, Button, Group } from "@mantine/core";
import { useTranslation } from "react-i18next";
import { createPortal } from "react-dom";
import { useEffect, useState, useRef, useCallback } from "react";
import DeleteIcon from "@mui/icons-material/Delete";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import { useRedaction } from "@app/contexts/RedactionContext";
import { useActiveDocumentId } from "@app/components/viewer/useActiveDocumentId";

export type { RedactionSelectionMenuProps };

export function RedactionSelectionMenu(props: any) {
  const activeDocumentId = useActiveDocumentId();

  // Don't render until we have a valid document ID
  if (!activeDocumentId) {
    return null;
  }

  return (
    <RedactionSelectionMenuInner documentId={activeDocumentId} {...props} />
  );
}

function RedactionSelectionMenuInner({
  documentId,
  context,
  selected,
  menuWrapperProps,
}: RedactionSelectionMenuProps & { documentId: string }) {
  const item =
    context?.type === "redaction"
      ? context.item
      : context?.type === "annotation"
        ? (context as any).annotation?.object
        : null;

  const isRedaction =
    context?.type === "redaction" ||
    (context?.type === "annotation" &&
      item?.type === PdfAnnotationSubtype.REDACT);

  const pageIndex = context?.pageIndex;
  const { t } = useTranslation();
  const { provides } = useEmbedPdfRedaction(documentId);
  const { setRedactionsApplied } = useRedaction();
  const wrapperRef = useRef<HTMLDivElement>(null);
  const [menuPosition, setMenuPosition] = useState<{
    top: number;
    left: number;
  } | null>(null);

  // Merge refs - menuWrapperProps.ref is a callback ref
  const setRef = useCallback(
    (node: HTMLDivElement | null) => {
      wrapperRef.current = node;
      // Call the EmbedPDF ref callback
      menuWrapperProps?.ref?.(node);
    },
    [menuWrapperProps],
  );

  const handleRemove = useCallback(() => {
    if (provides?.removePending && item && pageIndex !== undefined) {
      provides.removePending(pageIndex, item.id);
    }
  }, [provides, item, pageIndex]);

  const handleApply = useCallback(() => {
    if (provides?.commitPending && item && pageIndex !== undefined) {
      provides.commitPending(pageIndex, item.id);
      // Mark redactions as applied (but not yet saved) so the Save Changes button stays enabled
      // This ensures the button doesn't become disabled when pendingCount decreases
      setRedactionsApplied(true);
    }
  }, [provides, item, pageIndex, setRedactionsApplied]);

  // Calculate position for portal based on wrapper element
  useEffect(() => {
    if (!selected || !isRedaction || !item || !wrapperRef.current) {
      setMenuPosition(null);
      return;
    }

    const updatePosition = () => {
      const wrapper = wrapperRef.current;
      if (!wrapper) {
        setMenuPosition(null);
        return;
      }

      const wrapperRect = wrapper.getBoundingClientRect();
      // Position menu below the wrapper, centered
      // Use getBoundingClientRect which gives viewport-relative coordinates
      // Since we're using fixed positioning in the portal, we don't need to add scroll offsets
      setMenuPosition({
        top: wrapperRect.bottom + 8,
        left: wrapperRect.left + wrapperRect.width / 2,
      });
    };

    updatePosition();

    // Update position on scroll/resize
    window.addEventListener("scroll", updatePosition, true);
    window.addEventListener("resize", updatePosition);

    return () => {
      window.removeEventListener("scroll", updatePosition, true);
      window.removeEventListener("resize", updatePosition);
    };
  }, [selected, item]);

  // Early return AFTER all hooks have been called
  if (!selected || !isRedaction || !item) return null;

  const menuContent = menuPosition ? (
    <div
      style={{
        position: "fixed",
        top: `${menuPosition.top}px`,
        left: `${menuPosition.left}px`,
        transform: "translateX(-50%)",
        pointerEvents: "auto",
        zIndex: 10000, // Very high z-index to appear above everything
        backgroundColor: "var(--mantine-color-body)",
        borderRadius: 8,
        padding: "8px 12px",
        boxShadow: "0 2px 12px rgba(0, 0, 0, 0.25)",
        border: "1px solid var(--mantine-color-default-border)",
        // Fixed size to prevent browser zoom affecting layout
        fontSize: "14px",
        minWidth: "180px",
      }}
    >
      <Group gap="sm" wrap="nowrap" justify="center">
        <Tooltip label={t("viewer.redaction.removeMark", "Remove this mark")}>
          <ActionIcon
            variant="subtle"
            color="gray"
            size="md"
            onClick={handleRemove}
            styles={{
              root: {
                flexShrink: 0,
                backgroundColor: "var(--bg-raised)",
                border: "1px solid var(--border-default)",
                color: "var(--text-secondary)",
                "&:hover": {
                  backgroundColor: "var(--hover-bg)",
                  borderColor: "var(--border-strong)",
                  color: "var(--text-primary)",
                },
              },
            }}
          >
            <DeleteIcon style={{ fontSize: 18 }} />
          </ActionIcon>
        </Tooltip>

        <Tooltip
          label={t(
            "redact.manual.applyWarning",
            "⚠️ Permanent application, cannot be undone and the data underneath will be deleted",
          )}
          withArrow
          position="top"
        >
          <Button
            variant="filled"
            color="red"
            size="xs"
            onClick={handleApply}
            leftSection={<CheckCircleIcon style={{ fontSize: 16 }} />}
            styles={{
              root: { flexShrink: 0, whiteSpace: "nowrap" },
            }}
          >
            Apply (permanent)
          </Button>
        </Tooltip>
      </Group>
    </div>
  ) : null;

  return (
    <>
      {/* Invisible wrapper that provides positioning - uses EmbedPDF's menuWrapperProps */}
      <div
        ref={setRef}
        style={{
          // Use EmbedPDF's positioning styles
          ...menuWrapperProps?.style,
          // Keep the wrapper invisible but still occupying space for positioning
          opacity: 0,
          pointerEvents: "none",
        }}
      />
      {typeof document !== "undefined" && menuContent
        ? createPortal(menuContent, document.body)
        : null}
    </>
  );
}
