import { getTestDsn } from "../../__tests__/internal/getTestDsn";
import { Client } from "../createConnectedClient";
import type { SlotInfo } from "../getSlotInfo";
import { getSlotInfo } from "../getSlotInfo";

jest.useFakeTimers();
test("catches up eventually", async () => {
  const dsn = getTestDsn();

  const srcSpy = jest.spyOn(Client.prototype, "currentWalInsertLsn");
  const dstSpy = jest.spyOn(Client.prototype, "confirmedFlushLsn");

  let slotInfo: SlotInfo | undefined = undefined;

  expect(slotInfo).toBeUndefined();
  srcSpy.mockResolvedValue("0/3");
  dstSpy.mockResolvedValue("0/0");
  slotInfo = await getSlotInfo({ dsn, slotName: "test" }, slotInfo);
  expect(slotInfo.gap).toEqual(3);
  // dst=0x0 is behind lathed src=0x3.
  expect(slotInfo.gapTillLatch).toBe(3);
  expect(slotInfo.lagSec).toBeNull(); // lag is unknown yet

  jest.advanceTimersByTime(2000);

  expect(slotInfo.latched.srcLsn).toEqual("0/3");
  srcSpy.mockResolvedValue("0/5"); // src moved ->0x5
  dstSpy.mockResolvedValue("0/2"); // dst moved ->0x2
  slotInfo = await getSlotInfo({ dsn, slotName: "test" }, slotInfo);
  expect(slotInfo.gap).toEqual(3);
  // dst=0x2 is still behind lathed src=0x3.
  expect(slotInfo.gapTillLatch).toEqual(1);
  expect(slotInfo.lagSec).toBeNull(); // lag is still unknown

  jest.advanceTimersByTime(30000);

  expect(slotInfo.latched.srcLsn).toEqual("0/3");
  srcSpy.mockResolvedValue("0/8"); // src moved ->0x8
  dstSpy.mockResolvedValue("0/4"); // dst moved ->0x4
  slotInfo = await getSlotInfo({ dsn, slotName: "test" }, slotInfo);
  expect(slotInfo.gap).toEqual(4);
  // dst=0x4 became ahead of latched src=0x3, but it took 30 seconds - too long.
  expect(slotInfo.gapTillLatch).toEqual(0);
  expect(slotInfo.lagSec).toEqual(32);

  jest.advanceTimersByTime(2000);

  expect(slotInfo.latched.srcLsn).toEqual("0/8");
  srcSpy.mockResolvedValue("0/A"); // src moved ->0xA
  dstSpy.mockResolvedValue("0/7"); // dst moved ->0x7
  slotInfo = await getSlotInfo({ dsn, slotName: "test" }, slotInfo);
  expect(slotInfo.gap).toEqual(3);
  // dst=0x7 is still behind latched src=0x8.
  expect(slotInfo.gapTillLatch).toEqual(1);
  expect(slotInfo.lagSec).toEqual(32);

  jest.advanceTimersByTime(2000);

  expect(slotInfo.latched.srcLsn).toEqual("0/8");
  srcSpy.mockResolvedValue("0/B"); // src moved ->0xB
  dstSpy.mockResolvedValue("0/9"); // dst moved ->0x9
  slotInfo = await getSlotInfo({ dsn, slotName: "test" }, slotInfo);
  expect(slotInfo.gap).toEqual(2);
  // dst=0x9 became ahead of latched src=0x8
  expect(slotInfo.gapTillLatch).toEqual(0);
  expect(slotInfo.lagSec).toEqual(4);
});
