import { describe, expect, it } from "vitest";
import { createActor, waitFor } from "xstate";

import {
  createTestPrivateZoneMachine,
  loadPrivateZone,
  makeAlbum,
  makeAlbumsResponse,
  TEST_PRIVATE_ZONE_INPUT,
} from "./private-zone-machine.test-utils";

describe("private zone album flow", () => {
  it("loads albums for the supplied character", async () => {
    let loadedCharacterId: string | null = null;
    const actor = createActor(
      createTestPrivateZoneMachine({
        onLoad: ({ characterId }) => {
          loadedCharacterId = characterId;
        },
      }),
      { input: { characterId: "character_aria" } },
    ).start();

    actor.send({ type: "PrivateZoneInit" });
    await waitFor(actor, (snapshot) => snapshot.matches("ready"));

    expect(actor.getSnapshot().context.characterId).toBe("character_aria");
    expect(loadedCharacterId).toBe("character_aria");
    actor.stop();
  });

  it("loads only the first non-paginated album page", async () => {
    const actor = await loadPrivateZone({
      loadResponse: makeAlbumsResponse({
        items: Array.from({ length: 20 }, (_, index) => makeAlbum(index)),
      }),
    });
    expect(actor.getSnapshot().context.items).toHaveLength(20);
    expect(actor.getSnapshot().context).not.toHaveProperty("hasMore");
    expect(actor.getSnapshot().context).not.toHaveProperty("nextCursor");
    actor.stop();
  });

  it("keeps incomplete album metadata without creating a visible album", async () => {
    const actor = await loadPrivateZone({
      loadResponse: makeAlbumsResponse({
        items: [],
        pendingImageCount: 7,
        hasIncompleteContent: true,
      }),
    });

    expect(actor.getSnapshot().context.items).toEqual([]);
    expect(actor.getSnapshot().context.pendingImageCount).toBe(7);
    expect(actor.getSnapshot().context.hasIncompleteContent).toBe(true);
    actor.stop();
  });

  it("moves to failed when the album actor rejects", async () => {
    const actor = createActor(
      createTestPrivateZoneMachine({
        loadError: new Error("albums unavailable"),
      }),
      { input: TEST_PRIVATE_ZONE_INPUT },
    ).start();
    actor.send({ type: "PrivateZoneInit" });
    await waitFor(actor, (snapshot) => snapshot.matches("failed"));
    expect(actor.getSnapshot().context.errorMessage).toBe(
      "albums unavailable",
    );
    actor.stop();
  });
});
