import { setup, type ActionFunction, type EventObject } from "xstate";

import { getPendingAlbum } from "../helper/albums";
import type { PrivateZoneEvent } from "../private-zone-events";
import type { PrivateZoneState } from "../private-zone-state";
import {
  loadPrivateAlbumsActor,
  unlockPrivateAlbumActor,
} from "./actors/albums";

export interface PrivateZoneMachineInput {
  characterId: string;
}

export const basePrivateZoneMachineSetup = setup({
  types: {
    context: {} as PrivateZoneState,
    events: {} as PrivateZoneEvent,
    input: {} as PrivateZoneMachineInput,
  },
  actors: {
    loadAlbums: loadPrivateAlbumsActor,
    unlockAlbum: unlockPrivateAlbumActor,
  },
  guards: {
    hasPendingAlbum: ({ context }) => getPendingAlbum(context) !== null,
  },
});

type PrivateZoneActorAction<TEvent extends EventObject> = ActionFunction<
  PrivateZoneState,
  TEvent,
  PrivateZoneEvent,
  undefined,
  never,
  never,
  never,
  never,
  never
>;

export function createPrivateZoneActorActionSetup<
  TEvent extends EventObject,
>() {
  const actorActionSetup = setup({
    types: {
      context: {} as PrivateZoneState,
      events: {} as TEvent,
    },
  });
  return {
    assign(
      assignment: Parameters<typeof actorActionSetup.assign>[0],
    ): PrivateZoneActorAction<TEvent> {
      return actorActionSetup.assign(
        assignment,
      ) as unknown as PrivateZoneActorAction<TEvent>;
    },
  };
}
