/**
 * Stripe Payment Integration
 * 
 * Supports:
 * - Payment Intents (Cards, etc.)
 * - Webhook handling
 * - Refunds
 */

import Stripe from 'stripe';

// Initialize Stripe client
const stripeSecretKey = import.meta.env.STRIPE_SECRET_KEY;

export const stripe = new Stripe(stripeSecretKey || 'sk_test_placeholder', {
  apiVersion: '2025-01-27.acacia' as any,
});

// ============================================
// Types
// ============================================

export interface CreatePaymentIntentParams {
  amount: number; // in satang (THB = 100 satang)
  currency?: string;
  metadata?: Record<string, string>;
  customerId?: string;
  description?: string;
}

export interface PaymentIntentResult {
  clientSecret: string;
  paymentIntentId: string;
}

// ============================================
// Payment Intents
// ============================================

/**
 * Create a payment intent for checkout
 * Amount should be in satang (baht * 100)
 */
export async function createPaymentIntent(
  params: CreatePaymentIntentParams
): Promise<PaymentIntentResult> {
  const {
    amount,
    currency = 'thb',
    metadata = {},
    customerId,
    description,
  } = params;

  const paymentIntent = await stripe.paymentIntents.create({
    amount,
    currency,
    automatic_payment_methods: { enabled: true },
    metadata,
    ...(customerId && { customer: customerId }),
    ...(description && { description }),
  });

  if (!paymentIntent.client_secret) {
    throw new Error('Failed to create payment intent');
  }

  return {
    clientSecret: paymentIntent.client_secret,
    paymentIntentId: paymentIntent.id,
  };
}

/**
 * Retrieve a payment intent
 */
export async function getPaymentIntent(paymentIntentId: string) {
  return stripe.paymentIntents.retrieve(paymentIntentId);
}

/**
 * Confirm a payment intent
 */
export async function confirmPaymentIntent(
  paymentIntentId: string,
  paymentMethodId: string
) {
  return stripe.paymentIntents.confirm(paymentIntentId, {
    payment_method: paymentMethodId,
  });
}

/**
 * Cancel a payment intent
 */
export async function cancelPaymentIntent(paymentIntentId: string) {
  return stripe.paymentIntents.cancel(paymentIntentId);
}

// ============================================
// Webhooks
// ============================================

/**
 * Construct and verify webhook event
 */
export async function constructWebhookEvent(
  payload: string | Buffer,
  signature: string
) {
  const webhookSecret = import.meta.env.STRIPE_WEBHOOK_SECRET;
  
  if (!webhookSecret) {
    throw new Error('STRIPE_WEBHOOK_SECRET not configured');
  }

  return stripe.webhooks.constructEvent(payload, signature, webhookSecret);
}

/**
 * Parse webhook event safely
 */
export async function handleWebhook(
  payload: string | Buffer,
  signature: string,
  handlers: {
    onPaymentIntentSucceeded?: (intent: Stripe.PaymentIntent) => Promise<void>;
    onPaymentIntentFailed?: (intent: Stripe.PaymentIntent) => Promise<void>;
    onPaymentIntentProcessing?: (intent: Stripe.PaymentIntent) => Promise<void>;
  }
) {
  const event = await constructWebhookEvent(payload, signature);

  switch (event.type) {
    case 'payment_intent.succeeded':
      if (handlers.onPaymentIntentSucceeded) {
        await handlers.onPaymentIntentSucceeded(event.data.object as Stripe.PaymentIntent);
      }
      break;

    case 'payment_intent.payment_failed':
      if (handlers.onPaymentIntentFailed) {
        await handlers.onPaymentIntentFailed(event.data.object as Stripe.PaymentIntent);
      }
      break;

    case 'payment_intent.processing':
      if (handlers.onPaymentIntentProcessing) {
        await handlers.onPaymentIntentProcessing(event.data.object as Stripe.PaymentIntent);
      }
      break;

    default:
      console.log(`Unhandled webhook event type: ${event.type}`);
  }

  return event;
}

// ============================================
// Customers
// ============================================

/**
 * Create a Stripe customer
 */
export async function createCustomer(params: {
  email: string;
  name?: string;
  metadata?: Record<string, string>;
}) {
  return stripe.customers.create({
    email: params.email,
    name: params.name,
    metadata: params.metadata,
  });
}

/**
 * Get customer by ID
 */
export async function getCustomer(customerId: string) {
  return stripe.customers.retrieve(customerId);
}

/**
 * Update customer
 */
export async function updateCustomer(
  customerId: string,
  params: {
    email?: string;
    name?: string;
    metadata?: Record<string, string>;
  }
) {
  return stripe.customers.update(customerId, params);
}

// ============================================
// Refunds
// ============================================

/**
 * Create a refund
 */
export async function createRefund(params: {
  paymentIntentId: string;
  amount?: number; // partial refund amount in satang
  reason?: 'duplicate' | 'fraudulent' | 'requested_by_customer';
}) {
  return stripe.refunds.create({
    payment_intent: params.paymentIntentId,
    amount: params.amount,
    reason: params.reason,
  });
}

/**
 * Get refund status
 */
export async function getRefund(refundId: string) {
  return stripe.refunds.retrieve(refundId);
}

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

/**
 * Create a checkout session for hosted checkout
 */
export async function createCheckoutSession(params: {
  lineItems: Array<{
    price_data?: {
      currency: string;
      product_data: { name: string; description?: string; images?: string[] };
      unit_amount: number;
    };
    price?: string;
    quantity: number;
  }>;
  successUrl: string;
  cancelUrl: string;
  customerEmail?: string;
  metadata?: Record<string, string>;
  mode?: 'payment' | 'subscription';
}) {
  return stripe.checkout.sessions.create({
    mode: params.mode || 'payment',
    line_items: params.lineItems,
    success_url: params.successUrl,
    cancel_url: params.cancelUrl,
    customer_email: params.customerEmail,
    metadata: params.metadata,
  });
}

// ============================================
// Helpers
// ============================================

/**
 * Convert baht to satang (THB * 100)
 */
export function bahtToSatang(amount: number): number {
  return Math.round(amount * 100);
}

/**
 * Convert satang to baht
 */
export function satangToBaht(amount: number): number {
  return amount / 100;
}

/**
 * Format amount for Stripe (in smallest currency unit)
 */
export function formatAmount(amount: number, currency = 'thb'): number {
  // For THB, no decimal places
  if (currency.toLowerCase() === 'thb') {
    return Math.round(amount);
  }
  // For others, convert to cents
  return Math.round(amount * 100);
}

/**
 * Check if Stripe is configured
 */
export function isStripeConfigured(): boolean {
  return !!stripeSecretKey && !stripeSecretKey.includes('placeholder');
}
