"use client";

import { useEffect, useRef } from "react";
import { shallowEqual } from "@xstate/react";

import type { ChatLockType } from "@/data/schemas/chat";
import { behaviorAnalytics } from "@/lib/analytics";
import {
  consumePendingChatUnlock,
  peekPendingChatUnlock,
  type PendingChatUnlock,
  type PendingChatUnlockKind,
  type PendingChatPromotion,
} from "@/lib/navigation/chat_unlock_session";
import { useAppNavigator } from "@/router/use-app-navigator";
import {
  useChatDispatch,
  useChatSelector,
} from "@/stores/chat/chat-context";
import type { ChatUnlockPaywallRequest } from "@/stores/chat/chat-state";
import { useUserSelector } from "@/stores/user/user-context";

import { getInsufficientCreditsSubscriptionType } from "../chat-screen.helpers";

type PromotionScope = "any" | "only" | "exclude";

export interface MessageUnlockOptions {
  remoteMessageId?: string;
  lockType?: ChatLockType;
  clientLockId?: string;
  promotion?: PendingChatPromotion;
}

export interface UseChatUnlockNavigationFlowInput {
  returnUrl: string;
  expectedKind?: PendingChatUnlockKind;
  expectedMessageId?: string;
  ignoredKind?: PendingChatUnlockKind;
  promotionScope?: PromotionScope;
  enabled?: boolean;
}

export interface UseChatUnlockNavigationFlowOutput {
  unlockPaywallRequest: ChatUnlockPaywallRequest | null;
  requestMessageUnlock: (
    messageId: string,
    kind: PendingChatUnlockKind,
    options?: MessageUnlockOptions,
  ) => void;
  closeInsufficientCreditsDialog: () => void;
  confirmInsufficientCreditsDialog: () => void;
}

export function useChatUnlockNavigationFlow({
  returnUrl,
  expectedKind,
  expectedMessageId,
  ignoredKind,
  promotionScope = "any",
  enabled = true,
}: UseChatUnlockNavigationFlowInput): UseChatUnlockNavigationFlowOutput {
  const navigator = useAppNavigator();
  const isVip = useUserSelector((state) => state.context.isVip);
  const trackedPaywallRef = useRef<string | null>(null);
  const chatState = useChatSelector(
    (state) => ({
      historyLoaded: state.context.historyLoaded,
      unlockPaywallRequest: state.context.unlockPaywallRequest,
    }),
    shallowEqual,
  );
  const chatDispatch = useChatDispatch();
  const unlockPaywallRequest = getScopedUnlockPaywallRequest({
    request: chatState.unlockPaywallRequest,
    expectedKind,
    expectedMessageId,
    ignoredKind,
    promotionScope,
    enabled,
  });

  useEffect(() => {
    if (!unlockPaywallRequest) return;
    const requestKey = `${unlockPaywallRequest.displayMessageId}:${unlockPaywallRequest.clientLockId ?? ""}`;
    if (trackedPaywallRef.current === requestKey) return;
    trackedPaywallRef.current = requestKey;
    behaviorAnalytics.paywallShown(
      {
        entryPoint: "chat_unlock",
        triggerReason: unlockPaywallRequest.promotion
          ? "ad_landing"
          : "insufficient_credits",
      },
      { isVip },
    );
  }, [isVip, unlockPaywallRequest]);

  useEffect(() => {
    if (!enabled) return;
    if (!chatState.historyLoaded || !navigator.isAuthenticatedUser) return;

    let cancelled = false;

    const resumePendingUnlock = async () => {
      const pending = await peekPendingChatUnlock();
      if (
        cancelled ||
        !pending ||
        pending.returnUrl !== returnUrl ||
        !matchesPendingUnlockScope({
          pending,
          expectedKind,
          expectedMessageId,
          promotionScope,
        })
      ) {
        return;
      }

      const consumed = await consumePendingChatUnlock();
      if (cancelled || !consumed) return;

      chatDispatch({
        type: "ChatUnlockMessageRequested",
        messageId: consumed.displayMessageId,
        remoteMessageId: consumed.messageId,
        kind: consumed.kind,
        lockType: consumed.lockType,
        clientLockId: consumed.clientLockId,
      });
    };

    void resumePendingUnlock();
    return () => {
      cancelled = true;
    };
  }, [
    chatDispatch,
    chatState.historyLoaded,
    enabled,
    expectedKind,
    expectedMessageId,
    navigator.isAuthenticatedUser,
    promotionScope,
    returnUrl,
  ]);

  function requestMessageUnlock(
    messageId: string,
    kind: PendingChatUnlockKind,
    options: MessageUnlockOptions = {},
  ): void {
    const remoteMessageId =
      options.remoteMessageId ?? (options.lockType ? undefined : messageId);
    navigator.startMessageUnlock({
      displayMessageId: messageId,
      messageId: remoteMessageId,
      kind,
      lockType: options.lockType,
      clientLockId: options.clientLockId,
      promotion: options.promotion,
      returnUrl,
      onAuthenticated: () => {
        chatDispatch({
          type: "ChatUnlockMessageRequested",
          messageId,
          remoteMessageId,
          kind,
          lockType: options.lockType,
          clientLockId: options.clientLockId,
        });
      },
    });
  }

  function closeInsufficientCreditsDialog(): void {
    chatDispatch({ type: "ChatUnlockPaywallNavigationConsumed" });
  }

  function confirmInsufficientCreditsDialog(): void {
    if (!unlockPaywallRequest) return;

    chatDispatch({ type: "ChatUnlockPaywallNavigationConsumed" });
    navigator.openSubscriptionForPendingUnlock({
      displayMessageId: unlockPaywallRequest.displayMessageId,
      messageId: unlockPaywallRequest.messageId,
      kind: unlockPaywallRequest.kind,
      lockType: unlockPaywallRequest.lockType,
      clientLockId: unlockPaywallRequest.clientLockId,
      promotion: unlockPaywallRequest.promotion,
      returnUrl,
      type: getInsufficientCreditsSubscriptionType(isVip),
      analytics: {
        entryPoint: "chat_unlock",
        triggerReason: unlockPaywallRequest.promotion
          ? "ad_landing"
          : "insufficient_credits",
      },
    });
  }

  return {
    unlockPaywallRequest,
    requestMessageUnlock,
    closeInsufficientCreditsDialog,
    confirmInsufficientCreditsDialog,
  };
}

function getScopedUnlockPaywallRequest(input: {
  request: ChatUnlockPaywallRequest | null;
  expectedKind?: PendingChatUnlockKind;
  expectedMessageId?: string;
  ignoredKind?: PendingChatUnlockKind;
  promotionScope?: PromotionScope;
  enabled?: boolean;
}): ChatUnlockPaywallRequest | null {
  const {
    request,
    expectedKind,
    expectedMessageId,
    ignoredKind,
    promotionScope = "any",
    enabled = true,
  } = input;
  if (!enabled || !request) return null;
  if (promotionScope === "only" && !request.promotion) return null;
  if (promotionScope === "exclude" && request.promotion) return null;
  if (ignoredKind && request.kind === ignoredKind) return null;
  if (expectedKind && request.kind !== expectedKind) return null;
  if (
    expectedMessageId &&
    request.displayMessageId !== expectedMessageId &&
    request.messageId !== expectedMessageId
  ) {
    return null;
  }
  return request;
}

function matchesPendingUnlockScope(input: {
  pending: PendingChatUnlock;
  expectedKind?: PendingChatUnlockKind;
  expectedMessageId?: string;
  promotionScope?: PromotionScope;
}): boolean {
  const {
    pending,
    expectedKind,
    expectedMessageId,
    promotionScope = "any",
  } = input;
  if (promotionScope === "only" && !pending.promotion) return false;
  if (promotionScope === "exclude" && pending.promotion) return false;
  if (expectedKind && pending.kind !== expectedKind) return false;
  if (
    expectedMessageId &&
    pending.displayMessageId !== expectedMessageId &&
    pending.messageId !== expectedMessageId
  ) {
    return false;
  }
  return true;
}
