"use client";

import { useEffect, useMemo, useRef, type CSSProperties } from "react";
import Image from "next/image";
import { useRouter, useSearchParams } from "next/navigation";

import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
import {
  useChatDispatch,
  useChatState,
} from "@/stores/chat/chat-context";
import {
  useActiveCharacter,
  useActiveCharacterRoutes,
} from "@/providers/character-provider";
import { useCharacterCatalog } from "@/providers/character-catalog-provider";
import { clearPendingChatNavigation } from "@/lib/navigation/chat_unlock_session";
import { buildGlobalPageUrl } from "@/router/global-route-context";
import { resolveAuthenticatedNavigation } from "@/router/navigation-resolver";
import { getCharacterRoutes, ROUTE_BUILDERS, ROUTES } from "@/router/routes";
import type { ChatAction, CommercialAction } from "@/data/schemas/chat";
import { paymentApi } from "@/data/services/api";
import { behaviorAnalytics } from "@/lib/analytics";
import {
  recordChatActionEvent,
  rememberChatActionArrival,
} from "@/lib/chat/chat_action_events";

import { MobileShell } from "@/app/_components/core";

import {
  ChatArea,
  ChatHeader,
  ChatInputBar,
  ChatInsufficientCreditsBanner,
  ChatSupportButton,
  ChatUnlockDialogs,
  FullscreenImageViewer,
  PwaInstallOverlay,
} from "./components";
import {
  buildChatImageOverlayUrl,
  buildChatWithoutImageOverlayUrl,
  getChatImageOverlayMessageId,
} from "./chat-image-overlay-url";
import {
  deriveIsGuest,
} from "./chat-screen.helpers";
import { useChatSupportCta } from "./hooks/use-chat-support-cta";
import { useChatCommercialMessages } from "./hooks/use-chat-commercial-messages";
import { useChatUnlockCoordinator } from "./hooks/use-chat-unlock-coordinator";
import { useChatGuestLogin } from "./hooks/use-chat-guest-login";
import { useChatMessageLimitBanner } from "./hooks/use-chat-message-limit-banner";
import { useChatPromotionBootstrap } from "./hooks/use-chat-promotion-bootstrap";
import { useSplashLatestMessageSync } from "./hooks/use-splash-latest-message-sync";
import { resolveChatActionTarget } from "./chat-action-navigation";

const chatShellStyle = {
  "--chat-message-font-size": "clamp(16px, 3.333vw, 18px)",
  "--chat-message-line-height": "1.5",
} as CSSProperties;

export function ChatScreen() {
  const router = useRouter();
  const character = useActiveCharacter();
  const characterCatalog = useCharacterCatalog();
  const refreshCharacterCatalog = characterCatalog.refresh;
  const defaultCharacterSlug = characterCatalog.defaultCharacter.slug;
  const characterRoutes = useActiveCharacterRoutes();
  const profileUrl = buildGlobalPageUrl(
    ROUTES.profile,
    characterRoutes.chat,
  );
  const feedbackUrl = buildGlobalPageUrl(
    ROUTES.feedback,
    characterRoutes.chat,
  );
  const coinsRulesUrl = buildGlobalPageUrl(
    ROUTES.coinsRules,
    characterRoutes.chat,
  );
  const searchParams = useSearchParams();
  const state = useChatState();
  const chatDispatch = useChatDispatch();
  const authState = useAuthState();
  const authDispatch = useAuthDispatch();
  const imageOpenedFromChatRef = useRef(false);
  const imageViewerClosingRef = useRef(false);
  useSplashLatestMessageSync({
    characterId: state.characterId,
    historyLoaded: state.historyLoaded,
    loginStatus: authState.loginStatus,
    messages: state.historyMessages,
  });
  const isPromotionBootstrapReady = useChatPromotionBootstrap(
    state.characterId,
  );
  const visibleMessages = isPromotionBootstrapReady
    ? state.messages
    : state.historyMessages;
  const imageMessageId = getChatImageOverlayMessageId(searchParams);
  const imageReturnUrl = imageMessageId
    ? buildChatImageOverlayUrl(imageMessageId, characterRoutes.chat)
    : characterRoutes.chat;
  const unlockCoordinator = useChatUnlockCoordinator({
    defaultReturnUrl: characterRoutes.chat,
    imageMessageId,
    imageReturnUrl,
    promotion: state.promotion,
    enabled: isPromotionBootstrapReady,
  });
  const selectedImageMessage = useMemo(
    () =>
      imageMessageId
        ? visibleMessages.find(
            (item) =>
              (item.displayId === imageMessageId ||
                item.remoteId === imageMessageId) &&
              item.imageUrl,
          ) ?? null
        : null,
    [imageMessageId, visibleMessages],
  );

  // Guest status belongs to auth state and is not duplicated in the Chat actor.
  const isGuest = deriveIsGuest(authState.loginStatus);

  // 发送能力由后端统一返回，当前只处理积分不足引导。
  const messageLimitBanner = useChatMessageLimitBanner({
    upgradePromptVisible: state.upgradePromptVisible,
    upgradeReason: state.upgradeReason,
    paymentGuidance: state.paymentGuidance,
  });
  const supportCta = useChatSupportCta({
    characterId: character.id,
    historyLoaded: state.historyLoaded,
    loginStatus: authState.loginStatus,
  });
  useChatCommercialMessages({
    characterId: character.id,
    loginStatus: authState.loginStatus,
  });
  const shouldShowPwaInstall =
    state.historyLoaded && state.historyMessages.length >= 10;
  useChatGuestLogin({
    dispatch: authDispatch,
    hasInitialized: authState.hasInitialized,
    isLoading: authState.isLoading,
    loginStatus: authState.loginStatus,
  });

  useEffect(() => {
    if (!imageMessageId) {
      imageOpenedFromChatRef.current = false;
      imageViewerClosingRef.current = false;
    }
  }, [imageMessageId]);

  useEffect(() => {
    if (
      !imageMessageId ||
      !state.networkHistoryLoaded ||
      selectedImageMessage
    ) {
      return;
    }
    router.replace(
      buildChatWithoutImageOverlayUrl(searchParams, characterRoutes.chat),
      { scroll: false },
    );
  }, [
    characterRoutes.chat,
    imageMessageId,
    router,
    searchParams,
    selectedImageMessage,
    state.networkHistoryLoaded,
  ]);

  useEffect(() => {
    const errorCode = state.characterErrorCode;
    if (errorCode === "CHARACTER_MISMATCH") {
      chatDispatch({ type: "ChatHistoryRefreshRequested" });
      return;
    }
    if (
      errorCode !== "CHARACTER_DISABLED" &&
      errorCode !== "CHARACTER_NOT_FOUND"
    ) {
      return;
    }

    let cancelled = false;
    void (async () => {
      if (errorCode === "CHARACTER_NOT_FOUND") {
        await clearPendingChatNavigation();
      }
      await refreshCharacterCatalog();
      if (!cancelled) {
        router.replace(
          getCharacterRoutes(defaultCharacterSlug).splash,
        );
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [
    chatDispatch,
    defaultCharacterSlug,
    refreshCharacterCatalog,
    router,
    state.characterErrorCode,
  ]);

  function handleUnlockPrivateMessage(
    displayMessageId: string,
    remoteMessageId?: string,
  ): void {
    unlockCoordinator.requestMessageUnlock({
      displayMessageId,
      remoteMessageId,
      kind: "private",
    });
  }

  function handleUnlockVoiceMessage(
    displayMessageId: string,
    remoteMessageId?: string,
  ): void {
    unlockCoordinator.requestMessageUnlock({
      displayMessageId,
      remoteMessageId,
      kind: "voice",
    });
  }

  function handleUnlockImageMessage(
    displayMessageId: string,
    remoteMessageId?: string,
  ): void {
    unlockCoordinator.requestMessageUnlock({
      displayMessageId,
      remoteMessageId,
      kind: "image",
    });
  }

  function handleOpenImage(displayMessageId: string): void {
    imageOpenedFromChatRef.current = true;
    router.push(
      buildChatImageOverlayUrl(displayMessageId, characterRoutes.chat),
      { scroll: false },
    );
  }

  function handleCloseImageViewer(): void {
    if (imageViewerClosingRef.current) return;
    imageViewerClosingRef.current = true;
    if (imageOpenedFromChatRef.current) {
      imageOpenedFromChatRef.current = false;
      router.back();
      return;
    }
    router.replace(
      buildChatWithoutImageOverlayUrl(searchParams, characterRoutes.chat),
      { scroll: false },
    );
  }

  function handleUnlockImagePaywall(): void {
    if (!selectedImageMessage) return;
    unlockCoordinator.requestMessageUnlock({
      displayMessageId: selectedImageMessage.displayId,
      remoteMessageId: selectedImageMessage.remoteId,
      kind: "image",
    });
  }

  function handleOpenUserProfile(): void {
    router.push(
      resolveAuthenticatedNavigation({
        loginStatus: authState.loginStatus,
        targetUrl: profileUrl,
      }),
    );
  }

  function handleOpenCharacterPrivateZone(): void {
    router.push(characterRoutes.privateZone);
  }

  async function handleCommercialAction(action: CommercialAction): Promise<void> {
    behaviorAnalytics.elementClick(
      "chat.commercial_action.open",
      action.ctaLabel,
      {
        actionId: action.actionId,
        actionType: action.type,
        characterId: state.characterId,
        ruleId: action.ruleId,
        target: action.target,
      },
    );
    if (action.target === "discountConsent") {
      const offer = await paymentApi.acceptCommercialOffer(action.actionId);
      behaviorAnalytics.elementClick(
        "chat.commercial_action.accepted",
        action.ctaLabel,
        {
          actionId: action.actionId,
          actionType: action.type,
          characterId: state.characterId,
          planId: offer.planId,
          discountPercent: offer.discountPercent,
        },
      );
      router.push(
        ROUTE_BUILDERS.subscription(offer.subscriptionType, {
          sourceCharacterSlug: character.slug,
          returnTo: "chat",
          planId: offer.planId,
          commercialOfferId: offer.commercialOfferId,
        }),
      );
      return;
    }
    router.push(
      action.target === "giftCatalog"
        ? characterRoutes.tip
        : characterRoutes.privateZone,
    );
  }

  function handleCommercialActionDismiss(action: CommercialAction): void {
    behaviorAnalytics.elementClick(
      "chat.commercial_action.dismiss",
      "Dismiss commercial action",
      {
        actionId: action.actionId,
        actionType: action.type,
        characterId: state.characterId,
        ruleId: action.ruleId,
      },
    );
  }

  function handleChatActionViewed(action: ChatAction): void {
    void recordChatActionEvent(action, state.characterId, "viewed").catch(
      () => undefined,
    );
  }

  async function handleChatAction(action: ChatAction): Promise<void> {
    behaviorAnalytics.elementClick(
      "chat.action.open",
      action.ctaLabel,
      {
        actionId: action.actionId,
        actionKind: action.kind,
        actionType: action.type,
        characterId: state.characterId,
        ruleId: action.ruleId,
      },
    );
    await recordChatActionEvent(
      action,
      state.characterId,
      "opened",
    ).catch(() => undefined);

    const targetUrl = await resolveChatActionTarget(action, {
      characterRoutes,
      characterSlug: character.slug,
      profileUrl,
      feedbackUrl,
      coinsRulesUrl,
      getOrderStatus: (orderId) => paymentApi.getOrderStatus(orderId),
    });
    const authenticatedTarget = resolveAuthenticatedNavigation({
      loginStatus: authState.loginStatus,
      targetUrl,
    });
    rememberChatActionArrival(
      action,
      state.characterId,
      targetUrl,
    );
    router.push(authenticatedTarget);
  }

  function handleChatActionDismiss(action: ChatAction): void {
    behaviorAnalytics.elementClick(
      "chat.action.dismiss",
      "Dismiss chat action",
      {
        actionId: action.actionId,
        actionKind: action.kind,
        actionType: action.type,
        characterId: state.characterId,
        ruleId: action.ruleId,
      },
    );
    void recordChatActionEvent(
      action,
      state.characterId,
      "dismissed",
    ).catch(() => undefined);
  }

  return (
    <MobileShell>
      <div
        className="relative flex h-(--app-viewport-height,100dvh) flex-col overflow-hidden bg-(--color-dark-background,#111) text-(--color-text-primary,#fff)"
        style={chatShellStyle}
      >
        <div className="pointer-events-none absolute inset-0 z-0">
          <Image
            src={character.assets.chatBackground}
            alt=""
            fill
            priority
            sizes="(max-width: 540px) 100vw, 540px"
          />
        </div>

        <div className="relative z-1 flex min-h-0 flex-[1_1_auto] flex-col">
          <ChatHeader
            isGuest={isGuest}
            offerBanner={
              supportCta.visible ? (
                <ChatSupportButton
                  kind={supportCta.kind}
                  label={supportCta.label}
                  onClick={supportCta.open}
                />
              ) : null
            }
          />

          <ChatArea
            characterId={state.characterId}
            messages={visibleMessages}
            isReplyingAI={state.isReplyingAI}
            scrollToBottomSignal={state.outgoingMessageRevision}
            initialScrollReady={
              state.historyLoaded && isPromotionBootstrapReady
            }
            canLoadMoreHistory={state.hasMoreHistory}
            isLoadingMoreHistory={state.isLoadingMoreHistory}
            isUnlockingMessage={state.isUnlockingMessage}
            unlockingMessageId={state.unlockingMessageId}
            onUnlockPrivateMessage={handleUnlockPrivateMessage}
            onUnlockVoiceMessage={handleUnlockVoiceMessage}
            onUnlockImageMessage={handleUnlockImageMessage}
            onOpenImage={handleOpenImage}
            onUserAvatarClick={handleOpenUserProfile}
            onCharacterAvatarClick={handleOpenCharacterPrivateZone}
            onCommercialAction={handleCommercialAction}
            onCommercialActionDismiss={handleCommercialActionDismiss}
            onChatActionViewed={handleChatActionViewed}
            onChatAction={handleChatAction}
            onChatActionDismiss={handleChatActionDismiss}
            onLoadMoreHistory={() => {
              chatDispatch({ type: "ChatLoadMoreHistoryRequested" });
            }}
          />

          {messageLimitBanner.visible ? (
            <ChatInsufficientCreditsBanner
              title={messageLimitBanner.title}
              description={messageLimitBanner.description}
              ctaLabel={messageLimitBanner.ctaLabel}
              guidance={messageLimitBanner.guidance}
              onUnlock={messageLimitBanner.unlock}
            />
          ) : (
            <ChatInputBar
              disabled={!state.historyLoaded || !state.canSendMessage}
            />
          )}
        </div>

        {/* PWA 安装提示触发器（聊天消息数量达到阈值后才允许弹出） */}
        <PwaInstallOverlay enabled={shouldShowPwaInstall} />

        <ChatUnlockDialogs model={unlockCoordinator.dialogs} />

        {selectedImageMessage?.imageUrl ? (
          <FullscreenImageViewer
            characterId={state.characterId}
            remoteMessageId={selectedImageMessage.remoteId}
            imageUrl={selectedImageMessage.imageUrl}
            imagePaywalled={selectedImageMessage.imagePaywalled === true}
            isUnlockingImagePaywall={
              state.isUnlockingMessage &&
              state.unlockingMessageId === selectedImageMessage.displayId
            }
            onUnlockImagePaywall={handleUnlockImagePaywall}
            onClose={handleCloseImageViewer}
          />
        ) : null}
      </div>
    </MobileShell>
  );
}
