export const CHAT_KEYBOARD_VISIBLE_THRESHOLD_PX = 80;
export const CHAT_KEYBOARD_ZOOM_THRESHOLD = 1.05;
export const CHAT_KEYBOARD_TARGET_GAP_PX = 16;
export const CHAT_KEYBOARD_FALLBACK_WIDTH_RATIO = 0.84;
export const CHAT_KEYBOARD_FALLBACK_HEIGHT_RATIO = 0.43;
export const CHAT_KEYBOARD_FALLBACK_MIN_PX = 240;
export const CHAT_KEYBOARD_FALLBACK_MAX_PX = 340;

const CHAT_KEYBOARD_MAX_INSET_RATIO = 0.55;

export interface ChatKeyboardViewportBaseline {
  layoutHeight: number;
  layoutWidth: number;
  visualHeight: number;
}

export type ChatKeyboardFallbackViewport = Pick<
  ChatKeyboardViewportBaseline,
  "layoutHeight" | "layoutWidth"
>;

export interface ChatKeyboardViewportSnapshot {
  layoutHeight: number;
  visualHeight: number;
  visualScale: number;
  virtualKeyboardHeight: number;
}

export type ChatKeyboardInsetSource =
  | "content-resize"
  | "visual-viewport"
  | "virtual-keyboard"
  | "none";

export interface ChatKeyboardInsetResolution {
  keyboardVisible: boolean;
  bottomInset: number;
  source: ChatKeyboardInsetSource;
}

export function resolveChatKeyboardInset(
  baseline: ChatKeyboardViewportBaseline,
  snapshot: ChatKeyboardViewportSnapshot,
): ChatKeyboardInsetResolution {
  const contentResize = baseline.layoutHeight - snapshot.layoutHeight;
  if (contentResize > CHAT_KEYBOARD_VISIBLE_THRESHOLD_PX) {
    return {
      keyboardVisible: true,
      bottomInset: 0,
      source: "content-resize",
    };
  }

  const virtualKeyboardHeight = Math.max(0, snapshot.virtualKeyboardHeight);
  const visualViewportHeight =
    snapshot.visualScale <= CHAT_KEYBOARD_ZOOM_THRESHOLD
      ? Math.max(0, baseline.visualHeight - snapshot.visualHeight)
      : 0;
  const occludedHeight = Math.max(
    virtualKeyboardHeight,
    visualViewportHeight,
  );

  if (occludedHeight <= CHAT_KEYBOARD_VISIBLE_THRESHOLD_PX) {
    return {
      keyboardVisible: false,
      bottomInset: 0,
      source: "none",
    };
  }

  const maxInset = Math.round(
    baseline.layoutHeight * CHAT_KEYBOARD_MAX_INSET_RATIO,
  );

  return {
    keyboardVisible: true,
    bottomInset: Math.min(
      maxInset,
      Math.round(occludedHeight + CHAT_KEYBOARD_TARGET_GAP_PX),
    ),
    source:
      virtualKeyboardHeight >= visualViewportHeight
        ? "virtual-keyboard"
        : "visual-viewport",
  };
}

export function resolveChatKeyboardFallbackInset(
  viewport: ChatKeyboardFallbackViewport,
): number {
  const widthEstimate =
    viewport.layoutWidth * CHAT_KEYBOARD_FALLBACK_WIDTH_RATIO;
  const heightLimit =
    viewport.layoutHeight * CHAT_KEYBOARD_FALLBACK_HEIGHT_RATIO;
  const estimatedKeyboardHeight = Math.min(
    CHAT_KEYBOARD_FALLBACK_MAX_PX,
    Math.max(
      CHAT_KEYBOARD_FALLBACK_MIN_PX,
      Math.round(Math.min(widthEstimate, heightLimit)),
    ),
  );

  return estimatedKeyboardHeight + CHAT_KEYBOARD_TARGET_GAP_PX;
}
