import { describe, it, expect, beforeEach } from "vitest";
import { ScrollMemory, classifyNavigation } from "./scrollRestore";

describe("classifyNavigation", () => {
  it("treats the initial page load as an entry", () => {
    expect(classifyNavigation({ type: "enter" })).toBe("enter");
  });

  it("treats back/forward gestures as a popstate", () => {
    expect(classifyNavigation({ type: "popstate" })).toBe("popstate");
  });

  it("treats link and goto navigations as forward moves", () => {
    expect(classifyNavigation({ type: "link" })).toBe("forward");
    expect(classifyNavigation({ type: "goto" })).toBe("forward");
    expect(classifyNavigation({ type: "form" })).toBe("forward");
  });
});

describe("ScrollMemory", () => {
  let memory: ScrollMemory;

  beforeEach(() => {
    memory = new ScrollMemory();
  });

  // The bug: a scroll container that lives in a persistent layout keeps its
  // offset across a forward navigation, so a page opened from a scrolled list
  // starts part-way down. A forward move must always land at the top.
  it("resets to the top on a forward navigation, even from a scrolled page", () => {
    memory.save("/library", 1200);

    expect(memory.decide("/library/abc123", "forward")).toEqual({ kind: "reset" });
  });

  it("resets to the top when navigating forward to a page seen before", () => {
    memory.save("/library", 1200);
    memory.save("/search", 340);

    // Re-entering /library by tapping a nav link is a fresh visit, not a Back.
    expect(memory.decide("/library", "forward")).toEqual({ kind: "reset" });
  });

  it("restores the saved offset on Back", () => {
    memory.save("/library", 1200);

    expect(memory.decide("/library", "popstate")).toEqual({ kind: "restore", top: 1200 });
  });

  it("restores the top when Back targets a page with no saved offset", () => {
    expect(memory.decide("/library", "popstate")).toEqual({ kind: "restore", top: 0 });
  });

  it("keeps offsets per route rather than sharing one across pages", () => {
    memory.save("/library", 1200);
    memory.save("/search", 340);

    expect(memory.decide("/library", "popstate")).toEqual({ kind: "restore", top: 1200 });
    expect(memory.decide("/search", "popstate")).toEqual({ kind: "restore", top: 340 });
  });

  it("leaves the container alone on the initial load", () => {
    expect(memory.decide("/", "enter")).toEqual({ kind: "none" });
  });

  it("overwrites a stale offset when the same route is saved again", () => {
    memory.save("/library", 1200);
    memory.save("/library", 80);

    expect(memory.decide("/library", "popstate")).toEqual({ kind: "restore", top: 80 });
  });

  it("forgets nothing on decide, so a repeated Back still restores", () => {
    memory.save("/library", 1200);

    memory.decide("/library", "popstate");
    expect(memory.decide("/library", "popstate")).toEqual({ kind: "restore", top: 1200 });
  });
});
