"use client";

import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import {
  MoreHorizontal, Bookmark, Link as LinkIcon, EyeOff, Ban, Flag,
  Pencil, Trash2, Pin,
} from "lucide-react";
import type { Post } from "@/lib/types";

type Item = {
  label: string;
  icon: typeof Bookmark;
  action: () => void;
  destructive?: boolean;
};

/**
 * The post's own menu.
 *
 * Rendered into the body rather than inside the card: a card in a scrolling
 * feed has hidden overflow, which would clip it. Labels sit on the left and
 * icons on the right — deliberately the opposite way round from the repost
 * menu, so the two read as different things.
 */
export function PostMenu({
  post,
  isMine,
  onSave,
  onCopyLink,
  onHide,
  onBlock,
  onReport,
  onEdit,
  onDelete,
  onPin,
}: {
  post: Post;
  isMine: boolean;
  onSave: () => void;
  onCopyLink: () => void;
  onHide: () => void;
  onBlock: () => void;
  onReport: () => void;
  onEdit: () => void;
  onDelete: () => void;
  onPin: () => void;
}) {
  const [open, setOpen] = useState(false);
  const [at, setAt] = useState<{ x: number; y: number } | null>(null);
  const buttonRef = useRef<HTMLButtonElement | null>(null);

  useEffect(() => {
    if (!open) return;

    const place = () => {
      const r = buttonRef.current?.getBoundingClientRect();
      if (!r) return;

      // Right-aligned under the button, and flipped above it when there
      // isn't room below.
      const width = 300;
      const height = 260;
      const below = r.bottom + 6;
      const flip = below + height > window.innerHeight;

      setAt({
        x: Math.max(8, Math.min(r.right - width, window.innerWidth - width - 8)),
        y: flip ? r.top - 6 - height : below,
      });
    };
    place();

    const close = () => setOpen(false);
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") setOpen(false);
    };

    window.addEventListener("scroll", close, true);
    window.addEventListener("resize", place);
    window.addEventListener("keydown", onKey);
    return () => {
      window.removeEventListener("scroll", close, true);
      window.removeEventListener("resize", place);
      window.removeEventListener("keydown", onKey);
    };
  }, [open]);

  const run = (fn: () => void) => () => {
    setOpen(false);
    fn();
  };

  const items: Item[] = isMine
    ? [
        { label: "Edit", icon: Pencil, action: run(onEdit) },
        { label: "Pin to profile", icon: Pin, action: run(onPin) },
        { label: "Copy link", icon: LinkIcon, action: run(onCopyLink) },
        { label: "Delete", icon: Trash2, action: run(onDelete), destructive: true },
      ]
    : [
        { label: "Save", icon: Bookmark, action: run(onSave) },
        { label: "Copy link", icon: LinkIcon, action: run(onCopyLink) },
        { label: "Not interested", icon: EyeOff, action: run(onHide) },
        {
          label: `Block @${post.author.username}`,
          icon: Ban,
          action: run(onBlock),
          destructive: true,
        },
        { label: "Report content", icon: Flag, action: run(onReport), destructive: true },
      ];

  return (
    <>
      <button
        ref={buttonRef}
        onClick={(e) => {
          e.preventDefault();
          e.stopPropagation();
          setOpen((v) => !v);
        }}
        className="pm-trigger"
        title="More"
      >
        <MoreHorizontal size={18} strokeWidth={2} />
      </button>

      {open &&
        at &&
        typeof document !== "undefined" &&
        createPortal(
          <>
            <span className="pm-catch" onClick={() => setOpen(false)} />
            <div className="pm-panel" style={{ left: at.x, top: at.y }}>
              {items.map((item) => (
                <button
                  key={item.label}
                  onClick={item.action}
                  className={`pm-row ${item.destructive ? "danger" : ""}`}
                >
                  <span>{item.label}</span>
                  <item.icon size={20} strokeWidth={2} />
                </button>
              ))}
            </div>
          </>,
          document.body
        )}
    </>
  );
}
