import { useState, useEffect, useMemo } from 'react' import { Linking, Alert } from 'react-native' import { subscription, useSession } from '@/lib/auth' import type { StripePricingTableResponse, SubscriptionListItem } from '@/lib/auth' interface CreditPlan { amountInCents: number credits: number popular?: boolean name: string currency: string featureList: string[] } export function useMembership() { const { data: session } = useSession() const [selectedPlanIndex, setSelectedPlanIndex] = useState(0) const [stripePricingData, setStripePricingData] = useState(null) const [authSubscriptions, setAuthSubscriptions] = useState(null) const [isStripePricingLoading, setIsStripePricingLoading] = useState(false) const [isLoadingSubscriptions, setIsLoadingSubscriptions] = useState(false) const fetchStripePricing = async () => { setIsStripePricingLoading(true) const { data, error } = await subscription.plans({ query: { id: process.env.EXPO_PUBLIC_STRIPE_PRICING_TABLE_ID || '', key: process.env.EXPO_PUBLIC_STRIPE_PRICING_TABLE_KEY || '', }, }) setIsStripePricingLoading(false) if (!error) setStripePricingData(data) } const fetchAuthSubscriptions = async () => { if (!session?.user?.id) return setIsLoadingSubscriptions(true) const { data, error } = await subscription.list({ query: { referenceId: session.user.id }, }) setIsLoadingSubscriptions(false) if (!error) setAuthSubscriptions(data) } useEffect(() => { fetchStripePricing() }, []) useEffect(() => { if (session?.user?.id) fetchAuthSubscriptions() }, [session?.user?.id]) const licensedSubscriptions = authSubscriptions?.filter((sub: SubscriptionListItem) => sub.type === 'licenced') || [] const meteredSubscriptions = authSubscriptions?.filter((sub: SubscriptionListItem) => sub.type === 'metered') || [] const activeAuthSubscription = licensedSubscriptions.find( (sub: any) => sub.status === 'active' || sub.status === 'trialing' ) const hasActiveSubscription = !!( activeAuthSubscription && activeAuthSubscription.cancelAtPeriodEnd === false && activeAuthSubscription.status === 'active' ) const creditBalance = meteredSubscriptions?.[0]?.creditBalance?.remainingTokenBalance || 0 const creditPlans = useMemo((): CreditPlan[] => { if (!stripePricingData?.pricing_table_items) return [] return stripePricingData.pricing_table_items .filter((item) => item.recurring?.interval === 'month') .map((item) => ({ amountInCents: parseInt(item.amount), credits: parseInt(item.amount), popular: item.is_highlight || item.highlight_text === 'most_popular', name: item.name || '', currency: item.currency || 'usd', featureList: item.feature_list || [], })) }, [stripePricingData?.pricing_table_items]) const selectedPlan = creditPlans[selectedPlanIndex] || creditPlans[0] const createSubscription = async ({ priceId, productId }: { priceId: string; productId: string }) => { const { data, error } = await subscription.create({ priceId, productId, successUrl: `${process.env.EXPO_PUBLIC_APP_URL}/membership`, cancelUrl: `${process.env.EXPO_PUBLIC_APP_URL}/membership?canceled=true`, }) if (error) { Alert.alert('错误', '订阅创建失败') return } if (data?.url) await Linking.openURL(data.url) } const upgradeSubscription = async ({ credits }: { credits: number }) => { if (!activeAuthSubscription?.stripeSubscriptionId) { Alert.alert('错误', '未找到活跃订阅') return } const planIndex = creditPlans.findIndex(plan => plan.credits === credits) const planNames = stripePricingData?.pricing_table_items?.map((item: any) => item.product_name) || [] const planName = planNames[planIndex] || 'basic' const { data, error } = await subscription.upgrade({ plan: planName, subscriptionId: activeAuthSubscription.stripeSubscriptionId, successUrl: `${process.env.EXPO_PUBLIC_APP_URL}/membership`, cancelUrl: `${process.env.EXPO_PUBLIC_APP_URL}/membership?canceled=true`, }) if (error) { Alert.alert('错误', '订阅升级失败') return } } const restoreSubscription = async () => { if (!activeAuthSubscription) { Alert.alert('错误', '未找到可恢复的订阅') return } const { data, error } = await subscription.restore({ subscriptionId: activeAuthSubscription.stripeSubscriptionId, referenceId: activeAuthSubscription.referenceId, }) if (error) { Alert.alert('错误', '订阅恢复失败') return } Alert.alert('成功', '订阅已恢复') await fetchAuthSubscriptions() } const cancelSubscription = async () => { if (!activeAuthSubscription) { Alert.alert('错误', '未找到活跃订阅') return } const { data, error } = await subscription.cancel({ subscriptionId: activeAuthSubscription.stripeSubscriptionId, referenceId: activeAuthSubscription.referenceId, }) if (error) { Alert.alert('错误', '订阅取消失败') return } Alert.alert('成功', '订阅已取消') await fetchAuthSubscriptions() } const rechargeToken = async (amount: number) => { if (!amount || amount <= 0) { Alert.alert('错误', '充值金额无效') return } if (!meteredSubscriptions?.[0]?.priceId) { Alert.alert('错误', '定价数据不可用') return } const { data, error } = await subscription.credit.topup({ amount, priceId: meteredSubscriptions[0].priceId, successUrl: `${process.env.EXPO_PUBLIC_APP_URL}/membership`, cancelUrl: `${process.env.EXPO_PUBLIC_APP_URL}/membership?canceled=true`, }) if (error) { Alert.alert('错误', '充值失败') return } if (data?.url) await Linking.openURL(data.url) } return { selectedPlanIndex, selectedPlan, creditPlans, stripePricingData, session, activeAuthSubscription, hasActiveSubscription, creditBalance, isLoadingSubscriptions, isStripePricingLoading, setSelectedPlanIndex, createSubscription, upgradeSubscription, restoreSubscription, cancelSubscription, rechargeToken, refetchAuthSubscriptions: fetchAuthSubscriptions, } }