import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18n-lite";
import { booksApi } from "../api/books";
import { getApiErrorMessage } from "../api/errors";
import { useToast } from "../hooks/useToast";
import type { BookListItem } from "../types/book";
import styles from "./BookContextMenu.module.css";

type LibraryBook = BookListItem & { format: string; progressPercent: number | null };

interface BookContextMenuProps {
  book: LibraryBook;
  x: number;
  y: number;
  onClose: () => void;
  onBookUpdated: (book: LibraryBook) => void;
  onBookRemoved: (id: number) => void;
}

type ActionKind = "sync" | "remove" | null;

function clampPosition(x: number, y: number, width: number, height: number) {
  const padding = 8;
  const maxX = window.innerWidth - width - padding;
  const maxY = window.innerHeight - height - padding;
  return {
    left: Math.max(padding, Math.min(x, maxX)),
    top: Math.max(padding, Math.min(y, maxY)),
  };
}

export function BookContextMenu({
  book,
  x,
  y,
  onClose,
  onBookUpdated,
  onBookRemoved,
}: BookContextMenuProps) {
  const { t } = useTranslation();
  const { showToast } = useToast();
  const menuRef = useRef<HTMLDivElement>(null);
  const [position, setPosition] = useState({ left: x, top: y });
  const [activeAction, setActiveAction] = useState<ActionKind>(null);

  useLayoutEffect(() => {
    const el = menuRef.current;
    if (!el) return;
    setPosition(clampPosition(x, y, el.offsetWidth, el.offsetHeight));
  }, [x, y]);

  useEffect(() => {
    const handlePointerDown = (e: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
        onClose();
      }
    };
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    };
    const handleScroll = () => onClose();

    document.addEventListener("mousedown", handlePointerDown);
    document.addEventListener("keydown", handleKeyDown);
    window.addEventListener("scroll", handleScroll, true);

    return () => {
      document.removeEventListener("mousedown", handlePointerDown);
      document.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("scroll", handleScroll, true);
    };
  }, [onClose]);

  const handleSyncMetadata = async () => {
    setActiveAction("sync");
    try {
      const updated = await booksApi.enrichEBookMetadata(book.id);
      onBookUpdated({
        ...book,
        id: updated.id,
        title: updated.title,
        author: updated.author,
        genre: updated.format ? updated.format.toUpperCase() : "",
        format: updated.format,
        cover_image: updated.cover_image,
        progressPercent: book.progressPercent,
      });

      const status = updated.metadata?.match_status;
      if (status === "matched") {
        showToast({ message: t("toast.metadataSynced", { title: updated.title }), variant: "success" });
      } else if (status === "not_found") {
        showToast({ message: t("toast.noMatch"), variant: "warning" });
      } else {
        showToast({ message: t("toast.refreshDone"), variant: "success" });
      }
    } catch (err) {
      showToast({ message: getApiErrorMessage(err, t("common.unknownError")), variant: "error" });
    } finally {
      setActiveAction(null);
      onClose();
    }
  };

  const handleRemove = async () => {
    const confirmed = window.confirm(t("contextMenu.confirmRemove", { title: book.title }));
    if (!confirmed) return;

    setActiveAction("remove");
    try {
      await booksApi.deleteEBook(book.id);
      onBookRemoved(book.id);
      showToast({ message: t("toast.removed", { title: book.title }), variant: "success" });
    } catch (err) {
      showToast({ message: getApiErrorMessage(err, t("common.unknownError")), variant: "error" });
    } finally {
      setActiveAction(null);
      onClose();
    }
  };

  const busy = activeAction !== null;

  return (
    <div
      ref={menuRef}
      className={styles.menu}
      style={{ left: position.left, top: position.top }}
      role="menu"
      onClick={(e) => e.stopPropagation()}
      onContextMenu={(e) => e.preventDefault()}
    >
      <button
        type="button"
        className={`${styles.item} ${activeAction === "sync" ? styles.itemLoading : ""}`}
        role="menuitem"
        disabled={busy}
        onClick={() => void handleSyncMetadata()}
      >
        {activeAction === "sync" ? t("contextMenu.syncingMetadata") : t("contextMenu.syncMetadata")}
      </button>
      <div className={styles.separator} role="separator" />
      <button
        type="button"
        className={`${styles.item} ${styles.itemDanger} ${activeAction === "remove" ? styles.itemLoading : ""}`}
        role="menuitem"
        disabled={busy}
        onClick={() => void handleRemove()}
      >
        {activeAction === "remove" ? t("contextMenu.removing") : t("contextMenu.remove")}
      </button>
    </div>
  );
}
