/**
 * Stripe Checkout Module
 *
 * Handles checkout session creation for payments and subscriptions.
 */

import Stripe from 'stripe';
import { stripe, getStripeClientForOrganization } from './client';
import { logger } from '@/lib/logger';

// =============================================================================
// Checkout Sessions
// =============================================================================

/**
 * Create a checkout session for payment
 */
export async function createCheckoutSession(
  params: Stripe.Checkout.SessionCreateParams
): Promise<Stripe.Checkout.Session> {
  try {
    const session = await stripe.checkout.sessions.create({
      mode: 'payment',
      success_url: `${process.env.NEXT_PUBLIC_APP_URL}/payment/success?session_id={CHECKOUT_SESSION_ID}`,
      cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/payment/cancelled`,
      ...params,
    });
    return session;
  } catch (error) {
    logger.error('Error creating checkout session', error);
    throw error;
  }
}

/**
 * Create a subscription checkout session
 */
export async function createSubscriptionSession(
  params: Omit<Stripe.Checkout.SessionCreateParams, 'mode'>
): Promise<Stripe.Checkout.Session> {
  try {
    const session = await stripe.checkout.sessions.create({
      mode: 'subscription',
      success_url: `${process.env.NEXT_PUBLIC_APP_URL}/subscription/success?session_id={CHECKOUT_SESSION_ID}`,
      cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/subscription/cancelled`,
      ...params,
    });
    return session;
  } catch (error) {
    logger.error('Error creating subscription session', error);
    throw error;
  }
}

/**
 * Retrieve a checkout session
 */
export async function getCheckoutSession(
  sessionId: string
): Promise<Stripe.Checkout.Session | null> {
  try {
    const session = await stripe.checkout.sessions.retrieve(sessionId);
    return session;
  } catch (error) {
    logger.error('Error retrieving checkout session', error);
    return null;
  }
}

/**
 * Create a checkout session using organization-specific Stripe client if available
 */
export async function createCheckoutSessionForOrganization(
  organizationId: string | null,
  params: Stripe.Checkout.SessionCreateParams
): Promise<{
  session: Stripe.Checkout.Session;
  isCompanyKeys: boolean;
  mode: 'test' | 'live' | 'platform';
}> {
  let stripeClient: Stripe;
  let isCompanyKeys = false;
  let mode: 'test' | 'live' | 'platform' = 'platform';

  if (organizationId) {
    const result = await getStripeClientForOrganization(organizationId);
    stripeClient = result.client;
    isCompanyKeys = result.isCompanyKeys;
    mode = result.mode;
  } else {
    stripeClient = stripe as unknown as Stripe;
  }

  const session = await stripeClient.checkout.sessions.create({
    mode: 'payment',
    success_url: `${process.env.NEXT_PUBLIC_APP_URL}/payment/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/payment/cancelled`,
    ...params,
  });

  return { session, isCompanyKeys, mode };
}

/**
 * Create a deposit checkout session with Stripe Connect platform fee
 * Used when a merchant's customer pays a deposit - Mawidi takes 1.5% platform fee
 */
export async function createDepositCheckoutWithConnect(params: {
  organizationId: string;
  merchantStripeAccountId: string;
  amount: number; // in cents
  currency: string;
  customerEmail?: string;
  bookingMetadata: Record<string, string>;
  successUrl: string;
  cancelUrl: string;
}): Promise<Stripe.Checkout.Session> {
  const { organizationId, merchantStripeAccountId, amount, currency, customerEmail, bookingMetadata, successUrl, cancelUrl } = params;

  const platformFee = Math.round(amount * 0.015); // 1.5% platform fee

  const session = await stripe.checkout.sessions.create({
    mode: 'payment',
    line_items: [{
      price_data: {
        currency,
        product_data: { name: 'Appointment Deposit' },
        unit_amount: amount,
      },
      quantity: 1,
    }],
    payment_intent_data: {
      application_fee_amount: platformFee,
      transfer_data: {
        destination: merchantStripeAccountId,
      },
    },
    customer_email: customerEmail,
    metadata: {
      ...bookingMetadata,
      type: 'booking_deposit',
      organization_id: organizationId,
      platform_fee: platformFee.toString(),
    },
    success_url: successUrl,
    cancel_url: cancelUrl,
  });

  return session;
}

/**
 * Create a subscription with setup fee
 */
export async function createSubscriptionWithSetup(params: {
  customerId: string;
  priceId: string;
  setupFeeAmount: number;
  currency: string;
  metadata?: Record<string, string>;
}): Promise<Stripe.Checkout.Session> {
  const { customerId, priceId, setupFeeAmount, currency, metadata } = params;

  try {
    // Create setup fee as a one-time price
    const setupPrice = await stripe.prices.create({
      currency: currency.toLowerCase(),
      unit_amount: setupFeeAmount * 100, // Convert to cents
      product_data: {
        name: 'One-time Setup Fee',
      },
    });

    const session = await stripe.checkout.sessions.create({
      mode: 'subscription',
      customer: customerId,
      line_items: [
        {
          price: priceId,
          quantity: 1,
        },
        {
          price: setupPrice.id,
          quantity: 1,
        },
      ],
      subscription_data: {
        metadata: {
          ...metadata,
          has_setup_fee: 'true',
          setup_fee_amount: setupFeeAmount.toString(),
        },
        trial_period_days: 14,
      },
      success_url: `${process.env.NEXT_PUBLIC_APP_URL}/${metadata?.language || 'en'}/signup/verify?session_id={CHECKOUT_SESSION_ID}`,
      cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/${metadata?.language || 'en'}/signup?cancelled=true`,
    });

    return session;
  } catch (error) {
    logger.error('Error creating subscription with setup', error);
    throw error;
  }
}
