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

import {
  ALBUM_ID,
  COVER_URL,
  loadPrivateZone,
  makeUnlockResponse,
  unlockFirstAlbum,
} from "./private-zone-machine.test-utils";

describe("private zone unlock flow", () => {
  it("patches album images after a successful unlock", async () => {
    const actor = await loadPrivateZone();
    await unlockFirstAlbum(actor);
    expect(actor.getSnapshot().context.items[0]).toMatchObject({
      albumId: ALBUM_ID,
      locked: false,
      unlocked: true,
      lockDetail: { locked: false },
    });
    expect(actor.getSnapshot().context.items[0]?.images).toHaveLength(8);
    expect(actor.getSnapshot().context.unlockSuccessNonce).toBe(1);
    actor.stop();
  });

  it("exposes a paywall request when credits are low", async () => {
    const actor = await loadPrivateZone({
      unlockResponse: makeUnlockResponse({
        locked: true,
        unlocked: false,
        reason: "insufficient_credits",
        creditBalance: 100,
        shortfallCredits: 220,
        images: [{ url: COVER_URL, locked: true, index: 0 }],
      }),
    });
    await unlockFirstAlbum(actor);
    expect(actor.getSnapshot().context.unlockPaywallRequest).toEqual({
      albumId: ALBUM_ID,
      reason: "insufficient_credits",
      requiredCredits: 320,
      currentCredits: 100,
      shortfallCredits: 220,
    });
    actor.stop();
  });

  it("reloads when expected cost changes", async () => {
    let loadCount = 0;
    const actor = await loadPrivateZone({
      onLoad: () => {
        loadCount += 1;
      },
      unlockResponse: makeUnlockResponse({
        locked: true,
        unlocked: false,
        reason: "cost_changed",
      }),
    });
    await unlockFirstAlbum(actor);
    expect(loadCount).toBe(2);
    expect(actor.getSnapshot().context.unlockErrorMessage).toBe(
      "Unlock price changed. Please confirm again.",
    );
    actor.stop();
  });

  it("removes an album that no longer exists", async () => {
    const actor = await loadPrivateZone({
      unlockResponse: makeUnlockResponse({
        locked: true,
        unlocked: false,
        reason: "not_found",
        images: [],
      }),
    });
    await unlockFirstAlbum(actor);
    expect(actor.getSnapshot().context.items).toHaveLength(0);
    actor.stop();
  });

  it("keeps refunded persistence failures locked", async () => {
    const actor = await loadPrivateZone({
      unlockResponse: makeUnlockResponse({
        locked: true,
        unlocked: false,
        reason: "persist_failed_refunded",
        creditBalance: 500,
        images: [{ url: COVER_URL, locked: true, index: 0 }],
      }),
    });
    await unlockFirstAlbum(actor);
    expect(actor.getSnapshot().context.items[0]?.locked).toBe(true);
    expect(actor.getSnapshot().context.creditBalance).toBe(500);
    expect(actor.getSnapshot().context.unlockErrorMessage).toContain(
      "refunded",
    );
    actor.stop();
  });

  it("returns to ready when the unlock actor rejects", async () => {
    const actor = await loadPrivateZone({
      unlockError: new Error("unlock unavailable"),
    });
    await unlockFirstAlbum(actor);
    expect(actor.getSnapshot().context.unlockErrorMessage).toBe(
      "unlock unavailable",
    );
    actor.stop();
  });
});
