// packages/functions/src/shared/billing/createCheckout.ts

/**
 * @fileoverview Create Checkout Session Algorithm
 * @description Platform-agnostic algorithm for creating Stripe checkout sessions
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */

import type {
  CreateCheckoutSessionRequest,
  CreateCheckoutSessionResponse,
  StripeBackConfig,
} from '@donotdev/core/server';

/**
 * Provider interface for Stripe checkout operations
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
export interface StripeCheckoutProvider {
  createCheckoutSession(params: {
    priceId: string;
    customerEmail?: string;
    metadata: Record<string, string>;
    allowPromotionCodes: boolean;
    successUrl: string;
    cancelUrl: string;
    mode?: 'payment' | 'subscription';
  }): Promise<{
    id: string;
    url: string | null;
  }>;
}

/**
 * Provider interface for authentication operations
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
export interface AuthCheckoutProvider {
  getUser(userId: string): Promise<{
    customClaims?: Record<string, any>;
  }>;
}

/**
 * Create checkout session algorithm
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
export async function createCheckoutAlgorithm(
  request: CreateCheckoutSessionRequest,
  stripeProvider: StripeCheckoutProvider,
  authProvider: AuthCheckoutProvider,
  billingConfig: StripeBackConfig
): Promise<CreateCheckoutSessionResponse> {
  const {
    priceId,
    userId,
    customerEmail,
    metadata = {},
    allowPromotionCodes = true,
    successUrl,
    cancelUrl,
    mode = 'payment',
  } = request;

  // ✅ VALIDATE: billingConfigKey exists
  const configKey = metadata.billingConfigKey;
  if (!configKey) {
    throw new Error('Missing billingConfigKey in metadata');
  }

  // ✅ VALIDATE: config key is valid
  const billingItem = billingConfig[configKey];
  if (!billingItem) {
    throw new Error(`Invalid billing config key: ${configKey}`);
  }

  // ✅ VALIDATE: priceId matches config
  if (billingItem.priceId !== priceId) {
    throw new Error('Price ID mismatch with configuration');
  }

  // Verify user exists
  await authProvider.getUser(userId);

  // Create checkout session
  const session = await stripeProvider.createCheckoutSession({
    priceId,
    customerEmail,
    metadata: {
      userId,
      billingConfigKey: configKey, // ✅ ENSURE THIS IS SET
      ...metadata,
    },
    allowPromotionCodes,
    successUrl: successUrl || `${process.env.FRONTEND_URL}/billing/success`,
    cancelUrl: cancelUrl || `${process.env.FRONTEND_URL}/billing/cancel`,
    mode,
  });

  return {
    sessionId: session.id,
    sessionUrl: session.url,
  };
}
