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

import { bfsPath } from "./bfs-path";

describe("bfsPath", () => {
  const edges = [
    { from: "a", to: "b" },
    { from: "b", to: "c" },
    { from: "c", to: "d" },
    { from: "a", to: "e" },
    { from: "f", to: "g" },
  ];

  it("should include start node", () => {
    const result = bfsPath("a", edges);
    expect(result.nodeSet.has("a")).toBe(true);
  });

  it("should find forward-connected nodes", () => {
    const result = bfsPath("a", edges);
    expect(result.nodeSet.has("b")).toBe(true);
    expect(result.nodeSet.has("c")).toBe(true);
    expect(result.nodeSet.has("d")).toBe(true);
    expect(result.nodeSet.has("e")).toBe(true);
  });

  it("should find backward-connected nodes", () => {
    const result = bfsPath("d", edges);
    expect(result.nodeSet.has("c")).toBe(true);
    expect(result.nodeSet.has("b")).toBe(true);
    expect(result.nodeSet.has("a")).toBe(true);
  });

  it("should not include disconnected nodes", () => {
    const result = bfsPath("a", edges);
    expect(result.nodeSet.has("f")).toBe(false);
    expect(result.nodeSet.has("g")).toBe(false);
  });

  it("should collect edge keys for the path", () => {
    const result = bfsPath("b", edges);
    expect(result.edgeSet.has("b->c")).toBe(true);
    expect(result.edgeSet.has("c->d")).toBe(true);
    expect(result.edgeSet.has("a->b")).toBe(true);
  });

  it("should not include disconnected edge keys", () => {
    const result = bfsPath("a", edges);
    expect(result.edgeSet.has("f->g")).toBe(false);
  });

  it("should handle empty edges", () => {
    const result = bfsPath("x", []);
    expect(result.nodeSet.size).toBe(1);
    expect(result.nodeSet.has("x")).toBe(true);
    expect(result.edgeSet.size).toBe(0);
  });

  it("should handle cycles without infinite loop", () => {
    const cyclicEdges = [
      { from: "a", to: "b" },
      { from: "b", to: "c" },
      { from: "c", to: "a" },
    ];
    const result = bfsPath("a", cyclicEdges);
    expect(result.nodeSet.size).toBe(3);
    expect(result.edgeSet.size).toBe(3);
  });

  it("should handle node with no connections in graph", () => {
    const result = bfsPath("z", edges);
    expect(result.nodeSet.size).toBe(1);
    expect(result.nodeSet.has("z")).toBe(true);
    expect(result.edgeSet.size).toBe(0);
  });
});
