"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { MdMoreVert } from "react-icons/md";
import { useRouter } from "next/navigation";
import { AdminUser } from "../../../hooks/features/admin/users/useUsersFetch";

interface UserActionsMenuProps {
  user: AdminUser;
  onViewProfile?: (user: AdminUser) => void;
  onAddCredits?: (user: AdminUser) => void;
  onDeductCredits?: (user: AdminUser) => void;
  onDelete?: (userId: string | number) => void;
  onChangeStatus?: (userId: string | number, status: string) => void;
}

type MenuPosition = {
  top: number;
  left: number;
  origin: "top" | "bottom";
};

const MENU_WIDTH = 160;
const MENU_HEIGHT = 200;
const GAP = 8;
const SCREEN_PADDING = 12;

export function UserActionsMenu({
  user,
  onViewProfile,
  onAddCredits,
  onDeductCredits,
  onDelete,
  onChangeStatus,
}: UserActionsMenuProps) {
  const [open, setOpen] = useState(false);
  const [position, setPosition] = useState<MenuPosition>({
    top: 0,
    left: 0,
    origin: "top",
  });
  const router = useRouter();
  const buttonRef = useRef<HTMLButtonElement>(null);
  const menuRef = useRef<HTMLDivElement>(null);

  const updatePosition = useCallback(() => {
    const button = buttonRef.current;
    if (!button) return;

    const rect = button.getBoundingClientRect();

    const spaceBottom = window.innerHeight - rect.bottom;
    const spaceTop = rect.top;

    const openUp = spaceBottom < MENU_HEIGHT + GAP && spaceTop > spaceBottom;

    const top = openUp
      ? Math.max(SCREEN_PADDING, rect.top - MENU_HEIGHT - GAP)
      : Math.min(
          rect.bottom + GAP,
          window.innerHeight - MENU_HEIGHT - SCREEN_PADDING,
        );

    let left = rect.right - MENU_WIDTH;
    left = Math.max(SCREEN_PADDING, left);
    left = Math.min(left, window.innerWidth - MENU_WIDTH - SCREEN_PADDING);

    setPosition({
      top,
      left,
      origin: openUp ? "bottom" : "top",
    });
  }, []);

  const handleOpen = () => {
    updatePosition();
    setOpen((prev) => !prev);
  };

  useEffect(() => {
    if (!open) return;

    const handleOutsideClick = (event: MouseEvent) => {
      const target = event.target as Node;

      if (
        buttonRef.current?.contains(target) ||
        menuRef.current?.contains(target)
      ) {
        return;
      }

      setOpen(false);
    };

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "Escape") setOpen(false);
    };

    window.addEventListener("resize", updatePosition);
    window.addEventListener("scroll", updatePosition, true);
    document.addEventListener("mousedown", handleOutsideClick);
    document.addEventListener("keydown", handleKeyDown);

    return () => {
      window.removeEventListener("resize", updatePosition);
      window.removeEventListener("scroll", updatePosition, true);
      document.removeEventListener("mousedown", handleOutsideClick);
      document.removeEventListener("keydown", handleKeyDown);
    };
  }, [open, updatePosition]);

  const closeMenu = () => setOpen(false);

  const isActive = user.isActive;

  const menuItems = [
    {
      label: "View",
      onClick: () => {
        router.push(`/admin/users/${user.uuid}`);
        closeMenu();
      },
      className: "text-link-1",
    },
    {
      label: "Add Credits",
      onClick: () => {
        onAddCredits?.(user);
        closeMenu();
      },
      className: "text-text",
    },
    {
      label: "Deduct Credits",
      onClick: () => {
        onDeductCredits?.(user);
        closeMenu();
      },
      className: "text-text",
    },
    {
      label: isActive ? "Deactivate" : "Activate",
      onClick: () => {
        onChangeStatus?.(user.uuid, isActive ? "Inactive" : "Active");
        closeMenu();
      },
      className: "text-text",
    },
    {
      label: "Delete",
      onClick: () => {
        const isConfirmed = window.confirm(
          `Are you sure you want to delete ${user.name}?`,
        );

        if (!isConfirmed) return;

        onDelete?.(user.uuid);
        closeMenu();
      },
      className: "text-text hover:bg-danger-light hover:text-danger",
    },
  ];

  return (
    <>
      <button
        ref={buttonRef}
        type="button"
        onClick={handleOpen}
        aria-label="User actions"
        aria-haspopup="menu"
        aria-expanded={open}
        className="
          inline-flex h-8 w-8 items-center justify-center cursor-pointer
          rounded-full text-link-1 transition
          hover:bg-link-1/10 focus:outline-none
          focus:ring-2 focus:ring-link-1/30
        "
      >
        <MdMoreVert size={22} />
      </button>

      {open &&
        typeof document !== "undefined" &&
        createPortal(
          <div
            ref={menuRef}
            role="menu"
            style={{
              top: position.top,
              left: position.left,
              width: MENU_WIDTH,
              transformOrigin:
                position.origin === "top" ? "top right" : "bottom right",
            }}
            className="
              fixed z-9 overflow-hidden rounded-xl
              border border-black/5 bg-white py-1.5
              shadow-[0_12px_40px_rgba(15,23,42,0.18)]
              ring-1 ring-black/5
            "
          >
            {menuItems.map((item) => (
              <button
                key={item.label}
                type="button"
                role="menuitem"
                onClick={item.onClick}
                className={`
                  block w-full px-4 py-2.5 text-left cursor-pointer
                  font-body text-sm font-medium
                  transition-colors hover:bg-link-1/5
                  ${item.className}
                `}
              >
                {item.label}
              </button>
            ))}
          </div>,
          document.body,
        )}
    </>
  );
}