const MOBILE_SHEET_MQ = "(max-width: 768px)";

function getSheetParts(root) {
  if (!root) return null;
  const panel = root.querySelector(
    ".recipe-mobile-edit-sheet-panel, .ingredient-mobile-sheet-panel, .recipe-help-modal-panel"
  );
  const body = root.querySelector(
    ".recipe-mobile-edit-sheet-body, .ingredient-mobile-sheet-body, .recipe-help-modal-body"
  );
  const backdrop = root.querySelector(".recipe-mobile-edit-sheet-backdrop");
  return panel ? { root, panel, body, backdrop } : null;
}

export function resetRecipeMobileSheetPresentation(root) {
  const parts = getSheetParts(root);
  if (!parts) return;
  const { panel, backdrop } = parts;
  panel.style.transform = "";
  panel.style.transition = "";
  panel.classList.remove("recipe-mobile-edit-sheet--dragging");
  if (backdrop) {
    backdrop.style.opacity = "";
    backdrop.style.transition = "";
  }
}

function canStartSheetDrag(target, body) {
  if (target.closest(".recipe-mobile-edit-sheet-done")) return false;
  if (target.closest("button, input, select, textarea, a, label")) {
    return !!target.closest(".recipe-mobile-edit-sheet-grab, .recipe-mobile-edit-sheet-title");
  }
  if (target.closest(".recipe-mobile-edit-sheet-grab, .recipe-mobile-edit-sheet-header")) {
    return true;
  }
  if (body?.contains(target) && body.scrollTop <= 0) {
    return true;
  }
  return false;
}

function bindSheetGestures(root, onClose, mobileQuery) {
  const parts = getSheetParts(root);
  if (!parts || typeof onClose !== "function") return;

  const { panel, body, backdrop } = parts;
  let dragState = null;

  function clearDragState() {
    dragState = null;
    panel.classList.remove("recipe-mobile-edit-sheet--dragging");
  }

  function applyDrag(deltaY) {
    const offset = Math.max(0, deltaY);
    panel.style.transition = "none";
    panel.style.transform = `translateY(${offset}px)`;
    if (backdrop) {
      backdrop.style.transition = "none";
      backdrop.style.opacity = String(Math.max(0, 1 - offset / 280));
    }
  }

  function snapBack() {
    panel.style.transition = "transform 0.24s ease";
    panel.style.transform = "";
    if (backdrop) {
      backdrop.style.transition = "opacity 0.24s ease";
      backdrop.style.opacity = "";
    }
    window.setTimeout(() => {
      panel.style.transition = "";
      if (backdrop) backdrop.style.transition = "";
      clearDragState();
    }, 240);
  }

  function dismissWithAnimation() {
    panel.style.transition = "transform 0.22s ease";
    panel.style.transform = "translateY(100%)";
    if (backdrop) {
      backdrop.style.transition = "opacity 0.22s ease";
      backdrop.style.opacity = "0";
    }
    window.setTimeout(() => {
      resetRecipeMobileSheetPresentation(root);
      onClose();
    }, 220);
  }

  function onPointerDown(event) {
    if (!mobileQuery.matches || root.hidden) return;
    if (event.pointerType === "mouse" && event.button !== 0) return;
    if (!canStartSheetDrag(event.target, body)) return;

    dragState = {
      pointerId: event.pointerId,
      startY: event.clientY,
      fromScrollableBody: !!(body && body.contains(event.target) && !event.target.closest(".recipe-mobile-edit-sheet-header, .recipe-mobile-edit-sheet-grab")),
    };
    panel.classList.add("recipe-mobile-edit-sheet--dragging");
    panel.setPointerCapture(event.pointerId);
  }

  function onPointerMove(event) {
    if (!dragState || event.pointerId !== dragState.pointerId) return;

    const deltaY = event.clientY - dragState.startY;
    if (dragState.fromScrollableBody) {
      if (deltaY <= 0 || (body && body.scrollTop > 0)) {
        clearDragState();
        resetRecipeMobileSheetPresentation(root);
        return;
      }
      if (deltaY > 8) {
        dragState.fromScrollableBody = false;
      } else {
        return;
      }
    }

    if (deltaY > 0) {
      event.preventDefault();
      applyDrag(deltaY);
    }
  }

  function onPointerEnd(event) {
    if (!dragState || event.pointerId !== dragState.pointerId) return;

    const deltaY = event.clientY - dragState.startY;
    const threshold = Math.min(96, panel.offsetHeight * 0.2);
    clearDragState();

    if (deltaY > threshold) {
      dismissWithAnimation();
      return;
    }
    snapBack();
  }

  panel.addEventListener("pointerdown", onPointerDown);
  panel.addEventListener("pointermove", onPointerMove, { passive: false });
  panel.addEventListener("pointerup", onPointerEnd);
  panel.addEventListener("pointercancel", onPointerEnd);
}

export function initRecipeMobileSheetGestures(handlers = {}) {
  const mobileQuery = window.matchMedia(MOBILE_SHEET_MQ);
  const sheets = [
    {
      root: document.getElementById("ingredientMobileSheet"),
      onClose: handlers.closeIngredientMobileSheet,
    },
    {
      root: document.getElementById("unloadingGroupMobileSheet"),
      onClose: handlers.closeUnloadingGroupMobileSheet,
    },
    {
      root: document.getElementById("recipeHelpModal"),
      onClose: handlers.closeRecipeHelpModal,
    },
  ];

  sheets.forEach(({ root, onClose }) => bindSheetGestures(root, onClose, mobileQuery));
}
