export type FloatingPlacement = "bottom-start" | "bottom-end" | "top-start" | "top-end";

export interface RectLike {
  top: number;
  right: number;
  bottom: number;
  left: number;
  width: number;
  height: number;
}

export interface FloatingPositionOptions {
  anchor: RectLike;
  surfaceWidth: number;
  surfaceHeight: number;
  placement?: FloatingPlacement;
  offset?: number;
  viewportWidth?: number;
  viewportHeight?: number;
  viewportPadding?: number;
}

export interface FloatingPosition {
  top: number;
  left: number;
  maxHeight: number;
  resolvedPlacement: FloatingPlacement;
}

export function computeFloatingPosition({
  anchor,
  surfaceWidth,
  surfaceHeight,
  placement = "bottom-start",
  offset = 8,
  viewportWidth = typeof window === "undefined" ? 1920 : window.innerWidth,
  viewportHeight = typeof window === "undefined" ? 1080 : window.innerHeight,
  viewportPadding = 8,
}: FloatingPositionOptions): FloatingPosition {
  const roomBelow = viewportHeight - anchor.bottom - offset - viewportPadding;
  const roomAbove = anchor.top - offset - viewportPadding;
  const requestedTop = placement.startsWith("top");
  const shouldFlip = requestedTop
    ? surfaceHeight > roomAbove && roomBelow > roomAbove
    : surfaceHeight > roomBelow && roomAbove > roomBelow;
  const resolvedPlacement = shouldFlip
    ? (`${requestedTop ? "bottom" : "top"}-${placement.endsWith("end") ? "end" : "start"}` as FloatingPlacement)
    : placement;

  const alignedLeft = resolvedPlacement.endsWith("end")
    ? anchor.right - surfaceWidth
    : anchor.left;
  const left = Math.min(
    Math.max(viewportPadding, alignedLeft),
    Math.max(viewportPadding, viewportWidth - surfaceWidth - viewportPadding),
  );

  const availableHeight = resolvedPlacement.startsWith("top") ? roomAbove : roomBelow;
  const maxHeight = Math.max(96, availableHeight);
  const visibleHeight = Math.min(surfaceHeight, maxHeight);
  const top = resolvedPlacement.startsWith("top")
    ? Math.max(viewportPadding, anchor.top - offset - visibleHeight)
    : Math.min(anchor.bottom + offset, viewportHeight - visibleHeight - viewportPadding);

  return { top, left, maxHeight, resolvedPlacement };
}

