/**
 * Pure positioning logic for the person-mention hover card.
 *
 * Pulled out of TranscriptionReadView so the four placement branches
 * (default, flip-up, flip-left, both) plus the viewport clamp are unit-testable
 * without DOM. Sara's PR-B2 review #6 (no test for computeCardPosition) and
 * Leonie's FINDING-05 (320px overflow) both land here.
 */

/** Width of the rendered hover card. Mirrored in PersonHoverCard.svelte's CSS. */
export const CARD_WIDTH_PX = 320;

/** Min-height of the rendered hover card. Mirrored in PersonHoverCard.svelte's CSS. */
export const CARD_HEIGHT_PX = 180;

/** Gap between the mention rect and the card so they do not touch. */
export const CARD_GAP_PX = 6;

/**
 * Mentions in the bottom 30% of the viewport flip the card up by default,
 * even if it would numerically fit below — keeping the eye-line stable
 * is more important than minimal travel (Leonie #5329).
 */
export const BOTTOM_BAND_RATIO = 0.7;

/**
 * Mentions within this distance of the right viewport edge flip the card
 * left so it stays fully visible.
 */
export const RIGHT_FLIP_THRESHOLD_PX = 300;

export type Viewport = {
	viewportWidth: number;
	viewportHeight: number;
};

export type CardPosition = { top: number; left: number };

/**
 * Compute absolute-positioned top/left for the hover card, given a rect for
 * the mention anchor and the current viewport. Output is in document
 * coordinates (already includes scroll offsets).
 */
export function computeHoverCardPosition(rect: DOMRect, vp: Viewport): CardPosition {
	let top = rect.bottom + CARD_GAP_PX;
	let left = rect.left;

	const overflowsBottom = vp.viewportHeight - rect.bottom < CARD_HEIGHT_PX + CARD_GAP_PX;
	const inBottomBand = rect.top > vp.viewportHeight * BOTTOM_BAND_RATIO;
	if (overflowsBottom || inBottomBand) {
		top = rect.top - CARD_HEIGHT_PX - CARD_GAP_PX;
	}

	if (vp.viewportWidth - rect.left < RIGHT_FLIP_THRESHOLD_PX) {
		left = rect.right - CARD_WIDTH_PX;
	}

	// Clamp left so the card never extends past the right viewport edge
	// (FINDING-05: at 320px viewport the flip would otherwise produce a
	// negative left or right-side overflow).
	left = Math.min(left, vp.viewportWidth - CARD_WIDTH_PX - CARD_GAP_PX);

	return {
		top: Math.max(0, top),
		left: Math.max(0, left)
	};
}
