import { createChatPromotionState } from "../helper/promotion";
import { shouldPromptUnlockHistory } from "../helper/unlock";
import { initialState } from "../chat-state";
import {
  guestInitializingState,
  userInitializingState,
} from "./history-flow";
import {
  guestReadyState,
  guestSendingState,
  userSendingViaHttpState,
} from "./send-flow";
import {
  unlockingHistoryState,
  unlockingMessageState,
  unlockMachineSetup,
} from "./unlock-flow";

const startGuestSessionAction = unlockMachineSetup.assign(
  ({ context }) => ({
    ...initialState,
    promotion: context.promotion,
  }),
);

const startUserSessionAction = unlockMachineSetup.assign(
  ({ context }) => ({
    ...initialState,
    promotion: context.promotion,
  }),
);

const clearChatSessionAction = unlockMachineSetup.assign(() => ({
  ...initialState,
}));

const injectPromotionAction = unlockMachineSetup.assign(({ event }) => {
  if (event.type !== "ChatPromotionInjected") return {};
  return {
    promotion: createChatPromotionState(
      event.promotion,
      event.messageId,
    ),
  };
});

const clearPromotionAction = unlockMachineSetup.assign({ promotion: null });

export const chatMachineSetup = unlockMachineSetup.extend({
  actions: {
    startGuestSession: startGuestSessionAction,
    startUserSession: startUserSessionAction,
    clearChatSession: clearChatSessionAction,
    injectPromotion: injectPromotionAction,
    clearPromotion: clearPromotionAction,
  },
});

const idleState = chatMachineSetup.createStateConfig({
  on: {
    ChatGuestLogin: {
      target: "#chat.guestSession",
      actions: "startGuestSession",
    },
    ChatUserLogin: {
      target: "#chat.userSession",
      actions: "startUserSession",
    },
  },
});

const guestSessionState = chatMachineSetup.createStateConfig({
  invoke: [
    {
      id: "messageQueue",
      src: "httpMessageQueue",
    },
    {
      id: "loadHistory",
      src: "loadHistory",
    },
  ],
  on: {
    ChatUserLogin: {
      target: "#chat.userSession",
      actions: "startUserSession",
    },
    ChatNetworkHistoryLoaded: {
      actions: "applyNetworkHistoryLoaded",
    },
    ChatHistoryLoadFailed: {
      actions: "markHistoryLoadFailed",
    },
    ChatQueuedSendStarted: {
      actions: "markQueuedSendStarted",
    },
    ChatQueuedHttpDone: {
      actions: "applyQueuedHttpOutput",
    },
    ChatQueuedSendError: {
      actions: "appendQueuedSendErrorMessage",
    },
  },
  initial: "initializing",
  states: {
    initializing: guestInitializingState,
    ready: guestReadyState,
    sending: guestSendingState,
  },
});

const userReadyState = chatMachineSetup.createStateConfig({
  on: {
    ChatSendMessage: {
      guard: ({ context, event }) =>
        context.canSendMessage && event.content.trim().length > 0,
      actions: ["appendUserMessage", "enqueueMessage"],
    },
    ChatSendImage: {
      actions: "appendUserImage",
    },
    ChatUnlockMessageRequested: {
      guard: ({ event }) => event.messageId.trim().length > 0,
      target: "unlockingMessage",
      actions: "markUnlockMessageStarted",
    },
  },
});

const userSessionState = chatMachineSetup.createStateConfig({
  invoke: [
    {
      id: "messageQueue",
      src: "httpMessageQueue",
    },
    {
      id: "loadHistory",
      src: "loadHistory",
    },
  ],
  on: {
    ChatGuestLogin: {
      target: "#chat.guestSession",
      actions: "startGuestSession",
    },
    ChatLogout: {
      target: "#chat.idle",
      actions: "clearChatSession",
    },
    ChatNetworkHistoryLoaded: [
      {
        guard: ({ context, event }) =>
          event.type === "ChatNetworkHistoryLoaded" &&
          context.paymentUnlockPending &&
          shouldPromptUnlockHistory(event.output.messages),
        target: ".ready",
        actions: "showUnlockHistoryPromptFromNetwork",
      },
      {
        guard: ({ context }) => context.paymentUnlockPending,
        target: ".ready",
        actions: "applyNetworkHistoryLoadedAndClearPayment",
      },
      {
        guard: ({ context }) =>
          !context.isUnlockingHistory && !context.isUnlockingMessage,
        actions: "applyNetworkHistoryLoaded",
      },
    ],
    ChatHistoryLoadFailed: {
      actions: "markHistoryLoadFailed",
    },
    ChatQueuedSendStarted: {
      actions: "markQueuedSendStarted",
    },
    ChatQueuedHttpDone: {
      actions: "applyQueuedHttpOutput",
    },
    ChatQueuedSendError: {
      actions: "appendQueuedSendErrorMessage",
    },
    ChatPaymentSucceeded: [
      {
        guard: ({ context }) =>
          context.historyLoaded &&
          shouldPromptUnlockHistory(context.messages),
        actions: ["clearUpgradePrompt", "showUnlockHistoryPrompt"],
      },
      {
        guard: ({ context }) => !context.historyLoaded,
        actions: ["clearUpgradePrompt", "markPaymentUnlockPending"],
      },
      {
        guard: ({ context }) => context.historyLoaded,
        actions: ["clearUpgradePrompt", "dismissUnlockHistoryPrompt"],
      },
    ],
    ChatUnlockHistoryConfirmed: {
      target: ".unlockingHistory",
      actions: "markUnlockHistoryStarted",
    },
    ChatUnlockHistoryDismissed: {
      actions: "dismissUnlockHistoryPrompt",
    },
    ChatUnlockPaywallNavigationConsumed: {
      actions: "clearUnlockPaywallRequest",
    },
  },
  initial: "initializing",
  states: {
    initializing: userInitializingState,
    ready: userReadyState,
    sendingViaHttp: userSendingViaHttpState,
    unlockingHistory: unlockingHistoryState,
    unlockingMessage: unlockingMessageState,
  },
});

export const chatRootStateConfig = chatMachineSetup.createStateConfig({
  initial: "idle",
  on: {
    ChatPromotionInjected: { actions: "injectPromotion" },
    ChatPromotionCleared: { actions: "clearPromotion" },
  },
  states: {
    idle: idleState,
    guestSession: guestSessionState,
    userSession: userSessionState,
  },
});
