import { createActor, fromPromise, waitFor } from "xstate";

import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
import {
  PrivateAlbumUnlockResponseSchema,
  PrivateAlbumsResponseSchema,
  type PrivateAlbumUnlockResponse,
  type PrivateAlbumUnlockResponseInput,
  type PrivateAlbumsResponse,
  type PrivateAlbumsResponseInput,
} from "@/data/schemas/private-zone";
import { privateZoneMachine } from "@/stores/private-zone/private-zone-machine";

export const ALBUM_ID = "a1b2c3d4-0000-0000-0000-000000000000";
export const COVER_URL =
  "https://dbapi.banlv-ai.com/storage/v1/object/public/elio-schedules/01.jpg";
export const TEST_PRIVATE_ZONE_INPUT = {
  characterId: DEFAULT_CHARACTER_ID,
};

export function makeAlbum(index = 0) {
  return {
    albumId: index === 0 ? ALBUM_ID : `album-${index}`,
    title: `Private album ${index + 1}`,
    content: null,
    previewText: "Only for you.",
    imageCount: 8,
    images: [{ url: `${COVER_URL}?album=${index}`, locked: true, index: 0 }],
    locked: true,
    unlocked: false,
    unlockCost: 320,
    publishedAt: "2026-07-13T00:00:00+00:00",
    lockDetail: { locked: true },
  };
}

export function makeAlbumsResponse(
  overrides: Partial<PrivateAlbumsResponseInput> = {},
): PrivateAlbumsResponse {
  return PrivateAlbumsResponseSchema.parse({
    items: [makeAlbum()],
    creditBalance: 500,
    ...overrides,
  });
}

export function makeUnlockResponse(
  overrides: Partial<PrivateAlbumUnlockResponseInput> = {},
): PrivateAlbumUnlockResponse {
  return PrivateAlbumUnlockResponseSchema.parse({
    albumId: ALBUM_ID,
    locked: false,
    unlocked: true,
    reason: "ok",
    unlockCost: 320,
    requiredCredits: 320,
    creditBalance: 180,
    shortfallCredits: 0,
    images: Array.from({ length: 8 }, (_, index) => ({
      url: `${COVER_URL}?image=${index}`,
      locked: false,
      index,
    })),
    ...overrides,
  });
}

export function createTestPrivateZoneMachine(
  options: {
    loadResponse?: PrivateAlbumsResponse;
    unlockResponse?: PrivateAlbumUnlockResponse;
    loadError?: Error;
    unlockError?: Error;
    onLoad?: (input: { characterId: string }) => void;
  } = {},
) {
  return privateZoneMachine.provide({
    actors: {
      loadAlbums: fromPromise<PrivateAlbumsResponse, { characterId: string }>(
        async ({ input }) => {
          options.onLoad?.(input);
          if (options.loadError) throw options.loadError;
          return options.loadResponse ?? makeAlbumsResponse();
        },
      ),
      unlockAlbum: fromPromise(async () => {
        if (options.unlockError) throw options.unlockError;
        return options.unlockResponse ?? makeUnlockResponse();
      }),
    },
  });
}

export async function loadPrivateZone(
  options: Parameters<typeof createTestPrivateZoneMachine>[0] = {},
) {
  const actor = createActor(createTestPrivateZoneMachine(options), {
    input: TEST_PRIVATE_ZONE_INPUT,
  }).start();
  actor.send({ type: "PrivateZoneInit" });
  await waitFor(actor, (snapshot) => snapshot.matches("ready"));
  return actor;
}

export async function unlockFirstAlbum(
  actor: Awaited<ReturnType<typeof loadPrivateZone>>,
) {
  actor.send({
    type: "PrivateZoneUnlockRequested",
    albumId: ALBUM_ID,
  });
  actor.send({ type: "PrivateZoneUnlockConfirmed" });
  await waitFor(actor, (snapshot) => snapshot.matches("ready"));
}
