/**
 * Stripe Seats Module
 *
 * Handles additional seat purchases for organization subscriptions.
 */

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

// =============================================================================
// Seat Subscription Management
// =============================================================================

/**
 * Get current seat subscription item for an organization
 */
export async function getSeatSubscriptionItem(
  subscriptionId: string
): Promise<Stripe.SubscriptionItem | null> {
  try {
    const subscription = await stripe.subscriptions.retrieve(subscriptionId, {
      expand: ['items.data.price.product'],
    });

    // Find the seat subscription item by checking product metadata
    const seatItem = subscription.items.data.find((item) => {
      const product = item.price.product as Stripe.Product;
      return product.metadata?.type === 'additional_seat';
    });

    return seatItem || null;
  } catch (error) {
    logger.error('Error getting seat subscription item', error);
    return null;
  }
}

/**
 * Purchase additional seats for an organization
 */
export async function purchaseAdditionalSeats(params: {
  subscriptionId: string;
  organizationId: string;
  quantity: number;
  customerId: string;
  currency?: string;
}): Promise<{ success: boolean; error?: string }> {
  const { subscriptionId, organizationId, quantity, customerId, currency = 'gbp' } = params;

  try {
    if (quantity < 1) {
      return { success: false, error: 'Quantity must be at least 1' };
    }

    // Get the Stripe price ID for additional seats
    const prices = await stripe.prices.list({
      limit: 100,
      expand: ['data.product'],
    });

    const normalizedCurrency = currency.toLowerCase();
    const seatPrice = prices.data.find((price) => {
      const product = price.product as Stripe.Product;
      return (
        product.metadata?.type === 'additional_seat' &&
        price.currency === normalizedCurrency &&
        price.recurring?.interval === 'month'
      );
    });

    if (!seatPrice) {
      return {
        success: false,
        error: `Additional seat price not found in Stripe for currency '${normalizedCurrency}'. Please configure the seat product.`,
      };
    }

    // Check if seat item already exists
    const existingSeatItem = await getSeatSubscriptionItem(subscriptionId);

    if (existingSeatItem) {
      // Update existing seat quantity
      const newQuantity = (existingSeatItem.quantity || 0) + quantity;
      await stripe.subscriptionItems.update(existingSeatItem.id, {
        quantity: newQuantity,
        proration_behavior: 'create_prorations',
      });
    } else {
      // Add new seat subscription item
      await stripe.subscriptionItems.create({
        subscription: subscriptionId,
        price: seatPrice.id,
        quantity: quantity,
        proration_behavior: 'create_prorations',
        metadata: {
          organization_id: organizationId,
          type: 'additional_seats',
        },
      });
    }

    // Create and pay invoice immediately for the prorated amount
    try {
      const invoice = await stripe.invoices.create({
        customer: customerId,
        subscription: subscriptionId,
        auto_advance: true,
      });

      if (invoice.amount_due > 0) {
        await stripe.invoices.pay(invoice.id);
      }
    } catch (invoiceError) {
      // Invoice might fail if there's nothing to invoice (e.g., trial period)
      logger.debug('Invoice creation skipped or failed (may be in trial)', { error: invoiceError });
    }

    return { success: true };
  } catch (error) {
    logger.error('Error purchasing additional seats', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Failed to purchase seats',
    };
  }
}

/**
 * Update the quantity of additional seats
 */
export async function updateSeatQuantity(params: {
  subscriptionId: string;
  organizationId: string;
  newQuantity: number;
}): Promise<{ success: boolean; error?: string }> {
  const { subscriptionId, newQuantity } = params;

  try {
    if (newQuantity < 0) {
      return { success: false, error: 'Quantity cannot be negative' };
    }

    const seatItem = await getSeatSubscriptionItem(subscriptionId);

    if (!seatItem) {
      if (newQuantity === 0) {
        return { success: true };
      }

      return {
        success: false,
        error: 'No existing seat subscription. Use purchaseAdditionalSeats instead.',
      };
    }

    if (newQuantity === 0) {
      await stripe.subscriptionItems.del(seatItem.id, {
        proration_behavior: 'create_prorations',
      });
    } else {
      await stripe.subscriptionItems.update(seatItem.id, {
        quantity: newQuantity,
        proration_behavior: 'create_prorations',
      });
    }

    return { success: true };
  } catch (error) {
    logger.error('Error updating seat quantity', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Failed to update seats',
    };
  }
}

/**
 * Create Stripe checkout session for purchasing seats
 */
export async function createSeatCheckoutSession(params: {
  customerId: string;
  organizationId: string;
  quantity: number;
  successUrl: string;
  cancelUrl: string;
  currency?: string;
}): Promise<{ sessionId: string } | { error: string }> {
  const { customerId, organizationId, quantity, successUrl, cancelUrl, currency } = params;

  try {
    if (quantity < 1) {
      return { error: 'Quantity must be at least 1' };
    }

    const subscriptions = await stripe.subscriptions.list({
      customer: customerId,
      status: 'active',
      limit: 1,
    });

    if (!subscriptions.data.length) {
      return { error: 'No active subscription found' };
    }

    const subscription = subscriptions.data[0];
    const subscriptionCurrency = (currency || subscription.currency || 'gbp').toLowerCase();

    const prices = await stripe.prices.list({
      limit: 100,
      expand: ['data.product'],
    });

    const seatPrice = prices.data.find((price) => {
      const product = price.product as Stripe.Product;
      return (
        product.metadata?.type === 'additional_seat' &&
        price.currency === subscriptionCurrency &&
        price.recurring?.interval === 'month'
      );
    });

    if (!seatPrice) {
      return { error: `Additional seat price not found in Stripe for currency '${subscriptionCurrency}'` };
    }

    const existingSeatItem = await getSeatSubscriptionItem(subscription.id);
    const currentQuantity = existingSeatItem?.quantity || 0;
    const newQuantity = currentQuantity + quantity;

    const session = await stripe.checkout.sessions.create({
      mode: 'subscription',
      customer: customerId,
      line_items: [
        {
          price: seatPrice.id,
          quantity: quantity,
        },
      ],
      subscription_data: {
        metadata: {
          organization_id: organizationId,
          seat_purchase: 'true',
          previous_quantity: currentQuantity.toString(),
          new_quantity: newQuantity.toString(),
        },
      },
      success_url: successUrl,
      cancel_url: cancelUrl,
      allow_promotion_codes: false,
      billing_address_collection: 'auto',
    });

    return { sessionId: session.id };
  } catch (error) {
    logger.error('Error creating seat checkout session', error);
    return { error: error instanceof Error ? error.message : 'Failed to create checkout session' };
  }
}
