import { ApiRequestOptions } from '../hooks/useApi'; // ============================================================================ // TYPES — aligned with State Machine (wiki/concepts/Subscription-State-Machine.md) // ============================================================================ export type SubscriptionStatus = 'PENDING' | 'SCHEDULED' | 'TRIALING' | 'ACTIVE' | 'PAST_DUE' | 'EXPIRED'; export type BillingPeriod = 'MONTHLY' | 'YEARLY' | 'NONE'; export interface SubscriptionPlan { planKey: string; selectableByUser: boolean; title: Record; description: Record; currency: string; billingPeriod: BillingPeriod; pricePerUserCHF: number; pricePerFeatureInstanceCHF: number; autoRenew: boolean; maxUsers: number | null; maxFeatureInstances: number | null; trialDays: number | null; successorPlanKey: string | null; } export interface MandateSubscription { id: string; mandateId: string; planKey: string; status: SubscriptionStatus; recurring: boolean; startedAt: string; effectiveFrom: string | null; endedAt: string | null; currentPeriodStart: string | null; currentPeriodEnd: string | null; trialEndsAt: string | null; snapshotPricePerUserCHF: number; snapshotPricePerInstanceCHF: number; stripeSubscriptionId: string | null; } export interface SubscriptionStatusResponse { active: boolean; subscription: MandateSubscription | null; plan: SubscriptionPlan | null; scheduled: MandateSubscription | null; } export interface ActivatePlanResponse { redirectUrl?: string; [key: string]: unknown; } export type ApiRequestFunction = (options: ApiRequestOptions) => Promise; // ============================================================================ // Helpers // ============================================================================ function _mandateConfig(mandateId?: string): Record { if (!mandateId) return {}; return { headers: { 'X-Mandate-Id': mandateId } }; } // ============================================================================ // API FUNCTIONS // ============================================================================ export async function fetchSelectablePlans( request: ApiRequestFunction, mandateId?: string, ): Promise { return await request({ url: '/api/subscription/plans', method: 'get', additionalConfig: _mandateConfig(mandateId), }); } export async function fetchSubscriptionStatus( request: ApiRequestFunction, mandateId?: string, ): Promise { return await request({ url: '/api/subscription/status', method: 'get', additionalConfig: _mandateConfig(mandateId), }); } export async function activatePlan( request: ApiRequestFunction, planKey: string, mandateId?: string, returnUrl?: string, ): Promise { return await request({ url: '/api/subscription/activate', method: 'post', data: { planKey, returnUrl: returnUrl || '' }, additionalConfig: _mandateConfig(mandateId), }); } export async function cancelSubscription( request: ApiRequestFunction, subscriptionId: string, mandateId?: string, ): Promise> { return await request({ url: '/api/subscription/cancel', method: 'post', data: { subscriptionId }, additionalConfig: _mandateConfig(mandateId), }); } export async function reactivateSubscription( request: ApiRequestFunction, subscriptionId: string, mandateId?: string, ): Promise> { return await request({ url: '/api/subscription/reactivate', method: 'post', data: { subscriptionId }, additionalConfig: _mandateConfig(mandateId), }); } export async function verifyCheckout( request: ApiRequestFunction, sessionId: string, mandateId?: string, ): Promise<{ status: string; message: string }> { return await request({ url: '/api/subscription/checkout/verify', method: 'post', data: { sessionId }, additionalConfig: _mandateConfig(mandateId), }); }