"use client";

import { useEffect, useRef, useState } from "react";
import { useRouter } from "next/navigation";

import {
  persistExternalEntryPayload,
  resolveExternalEntryDestination,
  resolveExternalEntryPromotionType,
  resolveExternalEntryTarget,
  shouldBindExternalFacebookIdentity,
} from "@/lib/navigation/external_entry";
import {
  clearPendingChatPromotion,
  savePendingChatPromotion,
} from "@/lib/navigation/chat_unlock_session";
import { ROUTES } from "@/router/routes";
import {
  DEFAULT_CHARACTER_ID,
  getCharacterBySlug,
} from "@/data/constants/character";
import { Logger } from "@/utils/logger";
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";

const log = new Logger("ExternalEntryPersist");

interface ExternalEntryPersistProps {
  deviceId: string | null;
  asid: string | null;
  psid: string | null;
  avatarUrl: string | null;
  target: string | null;
  character: string | null;
  mode: string | null;
  promotionType: string | null;
}

export default function ExternalEntryPersist({
  deviceId,
  asid,
  psid,
  avatarUrl,
  target,
  character,
  mode,
  promotionType,
}: ExternalEntryPersistProps) {
  const router = useRouter();
  const authState = useAuthState();
  const authDispatch = useAuthDispatch();
  const [hasPersisted, setHasPersisted] = useState(false);
  const hasNavigatedRef = useRef(false);
  const hasReinitializedForPsidRef = useRef(false);
  const targetRoute = resolveExternalEntryTarget({ target });
  const destination = resolveExternalEntryDestination({ target, character });
  const characterId =
    getCharacterBySlug(character)?.id ?? DEFAULT_CHARACTER_ID;
  const resolvedPromotionType = resolveExternalEntryPromotionType({
    mode,
    promotionType,
  });

  useEffect(() => {
    let cancelled = false;

    void (async () => {
      const results = await Promise.allSettled([
        persistExternalEntryPayload({
          deviceId,
          asid,
          psid,
          avatarUrl,
        }),
        targetRoute === ROUTES.chat && resolvedPromotionType
          ? savePendingChatPromotion(resolvedPromotionType, characterId)
          : clearPendingChatPromotion(),
      ]);
      for (const result of results) {
        if (result.status === "rejected") {
          log.warn(
            "[ExternalEntryPersist] failed to persist payload",
            result.reason,
          );
        }
      }
      if (!cancelled) setHasPersisted(true);
    })();

    return () => {
      cancelled = true;
    };
  }, [
    avatarUrl,
    asid,
    character,
    characterId,
    destination,
    deviceId,
    mode,
    promotionType,
    psid,
    resolvedPromotionType,
    targetRoute,
  ]);

  useEffect(() => {
    if (hasNavigatedRef.current || !hasPersisted) return;

    // AuthStatusChecker can initialize before this entry has persisted PSID.
    // Re-run the check so PSID direct login is not skipped by that race.
    if (hasValue(psid) && !hasReinitializedForPsidRef.current) {
      if (!authState.hasInitialized || authState.isLoading) return;
      hasReinitializedForPsidRef.current = true;
      authDispatch({ type: "AuthInit" });
      return;
    }

    if (!authState.hasInitialized || authState.isLoading) return;
    hasNavigatedRef.current = true;

    if (
      shouldBindExternalFacebookIdentity({
        hasInitialized: authState.hasInitialized,
        isLoading: authState.isLoading,
        loginStatus: authState.loginStatus,
        asid,
        psid,
      })
    ) {
      authDispatch({
        type: "AuthExternalFacebookIdentityBindRequested",
        asid: asid ?? undefined,
        psid: psid ?? undefined,
      });
    }
    router.replace(destination);
  }, [
    asid,
    authDispatch,
    authState.hasInitialized,
    authState.isLoading,
    authState.loginStatus,
    destination,
    hasPersisted,
    psid,
    router,
  ]);

  return (
    <div
      className="flex flex-1 items-center justify-center"
      style={{ minHeight: "100dvh" }}
    >
      <div
        aria-label="Redirecting"
        className="size-10 animate-spin rounded-full border-4 border-t-transparent"
        style={{ borderColor: "var(--color-accent)" }}
      />
    </div>
  );
}

function hasValue(value: string | null): value is string {
  return typeof value === "string" && value.trim().length > 0;
}
