import { describe, expect, it } from "vitest";

import {
  resolveChatKeyboardFallbackInset,
  resolveChatKeyboardInset,
  type ChatKeyboardViewportBaseline,
  type ChatKeyboardViewportSnapshot,
} from "../chat-keyboard-geometry";

const baseline: ChatKeyboardViewportBaseline = {
  layoutHeight: 800,
  layoutWidth: 390,
  visualHeight: 760,
};

function makeSnapshot(
  overrides: Partial<ChatKeyboardViewportSnapshot> = {},
): ChatKeyboardViewportSnapshot {
  return {
    layoutHeight: 800,
    visualHeight: 760,
    visualScale: 1,
    virtualKeyboardHeight: 0,
    ...overrides,
  };
}

describe("resolveChatKeyboardInset", () => {
  it("does not add an inset when the content viewport already resized", () => {
    expect(
      resolveChatKeyboardInset(
        baseline,
        makeSnapshot({ layoutHeight: 500, visualHeight: 500 }),
      ),
    ).toEqual({
      keyboardVisible: true,
      bottomInset: 0,
      source: "content-resize",
    });
  });

  it("uses the visual viewport occlusion with the target gap", () => {
    expect(
      resolveChatKeyboardInset(
        baseline,
        makeSnapshot({ visualHeight: 460 }),
      ),
    ).toEqual({
      keyboardVisible: true,
      bottomInset: 316,
      source: "visual-viewport",
    });
  });

  it("prefers Virtual Keyboard geometry when available", () => {
    expect(
      resolveChatKeyboardInset(
        baseline,
        makeSnapshot({
          visualHeight: 520,
          virtualKeyboardHeight: 320,
        }),
      ),
    ).toEqual({
      keyboardVisible: true,
      bottomInset: 336,
      source: "virtual-keyboard",
    });
  });

  it("ignores visual viewport changes caused by page zoom", () => {
    expect(
      resolveChatKeyboardInset(
        baseline,
        makeSnapshot({ visualHeight: 460, visualScale: 1.2 }),
      ),
    ).toEqual({
      keyboardVisible: false,
      bottomInset: 0,
      source: "none",
    });
  });
});

describe("resolveChatKeyboardFallbackInset", () => {
  it.each([
    [{ layoutWidth: 320, layoutHeight: 568 }, 260],
    [{ layoutWidth: 360, layoutHeight: 640 }, 291],
    [{ layoutWidth: 390, layoutHeight: 844 }, 344],
    [{ layoutWidth: 430, layoutHeight: 932 }, 356],
  ])("fits common viewport %o", (viewport, expectedInset) => {
    expect(resolveChatKeyboardFallbackInset(viewport)).toBe(expectedInset);
  });

  it("covers the reported 392 by 760 Facebook viewport", () => {
    expect(
      resolveChatKeyboardFallbackInset({
        layoutWidth: 392,
        layoutHeight: 760,
      }),
    ).toBe(343);
  });

  it("stays stable across tall viewports with the same width", () => {
    expect(
      resolveChatKeyboardFallbackInset({
        layoutWidth: 390,
        layoutHeight: 760,
      }),
    ).toBe(343);
    expect(
      resolveChatKeyboardFallbackInset({
        layoutWidth: 390,
        layoutHeight: 900,
      }),
    ).toBe(344);
  });

  it("keeps the keyboard estimate within its bounds", () => {
    expect(
      resolveChatKeyboardFallbackInset({
        layoutWidth: 300,
        layoutHeight: 400,
      }),
    ).toBe(256);
    expect(
      resolveChatKeyboardFallbackInset({
        layoutWidth: 600,
        layoutHeight: 1_000,
      }),
    ).toBe(356);
  });
});
