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

import {
  PrivateAlbumUnlockResponseSchema,
  PrivateAlbumsResponseSchema,
  UnlockPrivateAlbumRequestSchema,
} from "@/data/schemas/private-zone";
import { ApiPath } from "@/data/services/api";

const ALBUM_ID = "a1b2c3d4-0000-0000-0000-000000000000";
const COVER_URL =
  "https://dbapi.banlv-ai.com/storage/v1/object/public/elio-schedules/01.jpg";

const lockedAlbum = {
  albumId: ALBUM_ID,
  momentId: `album:${ALBUM_ID}`,
  characterId: "elio",
  collectionKey: "manila_202607",
  title: "Private Manila set",
  content: null,
  previewText: "Only for you.",
  imageCount: 8,
  mediaCount: 8,
  images: [{ url: COVER_URL, type: "image", locked: true, index: 0 }],
  locked: true,
  unlocked: false,
  unlockCost: 320,
  requiredCredits: 320,
  creditCostPerImage: 40,
  currency: "credits",
  canUnlockWithCredits: false,
  publishedAt: "2026-07-13T00:00:00+00:00",
  lockDetail: {
    locked: true,
    showContent: false,
    showUpgrade: true,
    reason: "private_album",
  },
};

describe("Private Album schema models", () => {
  it("keeps shared payment guidance on an insufficient-credit response", () => {
    const response = PrivateAlbumUnlockResponseSchema.parse({
      albumId: ALBUM_ID,
      reason: "insufficient_credits",
      paymentGuidance: {
        guidanceId: "019c8f8d-17d3-7a42-b1cc-b6927b1927d5",
        characterId: "elio",
        characterName: "Elio Silvestri",
        scene: "privateZoneLocked",
        mode: "guide",
        title: "Keep talking with Elio",
        copy: "Baby, this album needs credits.",
        ctaLabel: "View VIP & credit options",
        purchaseOptions: ["vip", "topup"],
        target: "subscription",
        ruleId: "payment_guidance_privateZoneLocked",
      },
    });

    expect(response.paymentGuidance?.characterId).toBe("elio");
  });

  it("keeps a locked album cover URL while preserving the lock state", () => {
    const response = PrivateAlbumsResponseSchema.parse({
      items: [lockedAlbum],
      creditBalance: 100,
      nextCursor: null,
      hasMore: false,
    });

    expect(response.items[0]?.locked).toBe(true);
    expect(response.items[0]?.unlocked).toBe(false);
    expect(response.items[0]?.images[0]?.url).toBe(COVER_URL);
    expect(response.items[0]?.lockDetail).toEqual({ locked: true });
  });

  it("strips response fields that are not used by the frontend", () => {
    const response = PrivateAlbumsResponseSchema.parse({
      items: [lockedAlbum],
      creditBalance: 100,
      packageOptions: [{ imageCount: 8, creditCost: 320 }],
    });
    const albumJson = response.items[0];

    expect(albumJson).not.toHaveProperty("momentId");
    expect(albumJson).not.toHaveProperty("characterId");
    expect(albumJson).not.toHaveProperty("collectionKey");
    expect(response).not.toHaveProperty("packageOptions");
  });

  it("keeps incomplete-content metadata without exposing pending images", () => {
    const response = PrivateAlbumsResponseSchema.parse({
      items: [],
      creditBalance: 100,
      pendingImageCount: 7,
      hasIncompleteContent: true,
      pendingImages: [{ url: COVER_URL }],
    });

    expect(response.pendingImageCount).toBe(7);
    expect(response.hasIncompleteContent).toBe(true);
    expect(response).not.toHaveProperty("pendingImages");
  });

  it("parses an unlock response with all album images", () => {
    const response = PrivateAlbumUnlockResponseSchema.parse({
      albumId: ALBUM_ID,
      locked: false,
      unlocked: true,
      reason: "ok",
      unlockCost: 320,
      creditBalance: 180,
      images: Array.from({ length: 8 }, (_, index) => ({
        url: `${COVER_URL}?image=${index}`,
        locked: false,
        index,
      })),
      creditsCharged: 320,
    });

    expect(response.unlocked).toBe(true);
    expect(response.images).toHaveLength(8);
    expect(response.creditBalance).toBe(180);
    expect(response).not.toHaveProperty("creditsCharged");
  });

  it("serializes the expected unlock cost", () => {
    expect(
      UnlockPrivateAlbumRequestSchema.parse({ expectedCost: 320 }),
    ).toEqual({ expectedCost: 320 });
  });

  it("encodes the album id in the unlock path", () => {
    expect(ApiPath.privateZoneAlbumUnlock("album:91")).toBe(
      "/api/private-zone/albums/album%3A91/unlock",
    );
  });
});
