"use client";

import { useCallback, useMemo } from "react";

import { NavigationStorage } from "@/data/storage/navigation";
import {
  useActiveCharacter,
  useActiveCharacterRoutes,
} from "@/providers/character-provider";

import { type Route } from "./routes";
import type {
  OpenSubscriptionForPendingUnlockInput,
  OpenSubscriptionInput,
  StartMessageUnlockInput,
} from "./navigation-types";
import { useGlobalAppNavigator } from "./use-global-app-navigator";

export interface AppNavigator {
  push: (href: string, options?: { scroll?: boolean }) => void;
  replace: (href: string, options?: { scroll?: boolean }) => void;
  back: () => void;
  openAuth: (redirectTo?: string) => void;
  openChat: (options?: { replace?: boolean; scroll?: boolean }) => void;
  openSubscription: (input: OpenSubscriptionInput) => void;
  startMessageUnlock: (input: StartMessageUnlockInput) => void;
  openSubscriptionForPendingUnlock: (
    input: OpenSubscriptionForPendingUnlockInput,
  ) => void;
  getDefaultPayChannel: ReturnType<
    typeof useGlobalAppNavigator
  >["getDefaultPayChannel"];
  isAuthenticatedUser: boolean;
}

export function useAppNavigator(): AppNavigator {
  const globalNavigator = useGlobalAppNavigator();
  const character = useActiveCharacter();
  const characterRoutes = useActiveCharacterRoutes();
  const {
    back,
    getDefaultPayChannel,
    isAuthenticatedUser,
    push,
    replace,
  } = globalNavigator;

  const openAuth = useCallback(
    (redirectTo: string = characterRoutes.chat): void => {
      globalNavigator.openAuth(redirectTo);
    },
    [characterRoutes.chat, globalNavigator],
  );

  const openChat = useCallback(
    (options: { replace?: boolean; scroll?: boolean } = {}): void => {
      const navOptions = { scroll: options.scroll ?? false };
      if (options.replace) {
        replace(characterRoutes.chat, navOptions);
        return;
      }
      push(characterRoutes.chat, navOptions);
    },
    [characterRoutes.chat, push, replace],
  );

  const openSubscription = useCallback(
    (input: OpenSubscriptionInput): void => {
      globalNavigator.openSubscription({
        ...input,
        sourceCharacterSlug: character.slug,
      });
    },
    [character.slug, globalNavigator],
  );

  const startMessageUnlock = useCallback(
    ({
      displayMessageId,
      messageId,
      kind,
      lockType,
      clientLockId,
      promotion,
      returnUrl,
      stage = "auth",
      onAuthenticated,
    }: StartMessageUnlockInput): void => {
      if (isAuthenticatedUser) {
        onAuthenticated();
        return;
      }

      void (async () => {
        await NavigationStorage.savePendingChatUnlock({
          characterId: character.id,
          displayMessageId,
          messageId,
          kind,
          lockType,
          clientLockId,
          promotion,
          returnUrl,
          stage,
        });
        globalNavigator.openAuth(returnUrl);
      })();
    },
    [character.id, globalNavigator, isAuthenticatedUser],
  );

  const openSubscriptionForPendingUnlock = useCallback(
    ({
      displayMessageId,
      messageId,
      kind,
      lockType,
      clientLockId,
      promotion,
      returnUrl,
      type,
      payChannel = getDefaultPayChannel(),
      analytics,
      chatActionId,
    }: OpenSubscriptionForPendingUnlockInput): void => {
      void (async () => {
        await NavigationStorage.savePendingChatUnlock({
          characterId: character.id,
          displayMessageId,
          messageId,
          kind,
          lockType,
          clientLockId,
          promotion,
          returnUrl,
          stage: "payment",
        });
        openSubscription({
          type,
          payChannel,
          returnTo: "chat",
          analytics,
          chatActionId,
        });
      })();
    },
    [character.id, getDefaultPayChannel, openSubscription],
  );

  return useMemo(() => ({
    push,
    replace,
    back,
    openAuth,
    openChat,
    openSubscription,
    startMessageUnlock,
    openSubscriptionForPendingUnlock,
    getDefaultPayChannel,
    isAuthenticatedUser,
  }), [
    back,
    getDefaultPayChannel,
    isAuthenticatedUser,
    openAuth,
    openChat,
    openSubscription,
    openSubscriptionForPendingUnlock,
    push,
    replace,
    startMessageUnlock,
  ]);
}

export type { Route };
