"use client"; import { type Dispatch, useEffect, useRef } from "react"; import type { PayChannel } from "@/data/schemas/payment"; import type { PendingPaymentSubscriptionType } from "@/lib/payment/pending_payment_order"; import { usePaymentDispatch, usePaymentState, type PaymentContextState, } from "@/stores/payment/payment-context"; import type { PaymentEvent } from "@/stores/payment/payment-events"; import type { PaymentPlanCatalog } from "@/stores/payment/payment-state"; import { usePendingPaymentOrderLifecycle } from "./use-pending-payment-order-lifecycle"; export interface UsePaymentRouteFlowInput { catalog?: PaymentPlanCatalog; initialPayChannel: PayChannel; paymentType: PendingPaymentSubscriptionType; shouldResumePendingOrder: boolean; characterId?: string; initialCategory?: string | null; initialPlanId?: string | null; initialAutoRenew?: boolean | null; commercialOfferId?: string | null; resumeOrderId?: string | null; chatActionId?: string | null; } export interface PaymentRouteFlow { payment: PaymentContextState; paymentDispatch: Dispatch; } /** * Owns the lifecycle shared by payment entry routes: * initialize the requested catalog and restore or clean up redirect orders. */ export function usePaymentRouteFlow({ catalog = "default", initialPayChannel, paymentType, shouldResumePendingOrder, characterId, initialCategory = null, initialPlanId = null, initialAutoRenew = null, commercialOfferId = null, resumeOrderId = null, chatActionId = null, }: UsePaymentRouteFlowInput): PaymentRouteFlow { const payment = usePaymentState(); const paymentDispatch = usePaymentDispatch(); const initializedCatalogKeyRef = useRef(null); const resumedOrderIdRef = useRef(null); const catalogKey = [ catalog, characterId ?? "", initialCategory ?? "", initialPlanId ?? "", initialAutoRenew === null ? "" : String(initialAutoRenew), commercialOfferId ?? "", chatActionId ?? "", ].join(":"); usePendingPaymentOrderLifecycle({ payment, paymentDispatch, paymentType, shouldResumePendingOrder, }); useEffect(() => { if (initializedCatalogKeyRef.current === catalogKey) return; initializedCatalogKeyRef.current = catalogKey; paymentDispatch({ type: "PaymentInit", catalog, payChannel: initialPayChannel, ...(characterId ? { characterId } : {}), ...(initialCategory ? { category: initialCategory } : {}), ...(initialPlanId ? { planId: initialPlanId } : {}), ...(initialAutoRenew === null ? {} : { autoRenew: initialAutoRenew }), ...(commercialOfferId ? { commercialOfferId } : {}), ...(chatActionId ? { chatActionId } : {}), }); }, [ catalog, catalogKey, characterId, commercialOfferId, chatActionId, initialCategory, initialPlanId, initialAutoRenew, initialPayChannel, paymentDispatch, ]); useEffect(() => { if (!resumeOrderId || resumedOrderIdRef.current === resumeOrderId) return; resumedOrderIdRef.current = resumeOrderId; paymentDispatch({ type: "PaymentReturned", orderId: resumeOrderId }); }, [paymentDispatch, resumeOrderId]); return { payment, paymentDispatch }; }