export const prerender = false;

import type { APIRoute } from 'astro';
import { supabase } from '../../../lib/supabase';
import { validateRequest, sanitizeString, sanitizeEmail } from '../../../lib/validation';
import { getClientIP, checkRateLimit, createAuthResponse } from '../../../lib/auth';
import { z } from 'zod';

// Validation schema for purchase attempt
const purchaseAttemptSchema = z.object({
  session_id: z.string().min(1).max(200),
  event_id: z.string().uuid(),
  purchaser_email: z.string().email(),
  purchaser_name: z.string().min(1).max(100),
  items: z.array(z.object({
    ticket_type_id: z.string().uuid(),
    quantity: z.number().int().positive().max(10),
    unit_price: z.number().int().nonnegative(),
    seat_id: z.string().uuid().optional()
  })).min(1).max(20),
  platform_fee: z.number().int().nonnegative().optional(),
  hold_minutes: z.number().int().min(5).max(120).optional()
});

export const POST: APIRoute = async ({ request }) => {
  try {
    // Rate limiting
    const clientIP = getClientIP(request);
    if (!checkRateLimit(`purchase-attempt:${clientIP}`, 5, 60000)) { // 5 requests per minute
      return createAuthResponse({ error: 'Rate limit exceeded' }, 429);
    }

    const body = await request.json();
    
    // Validate input
    const validation = validateRequest(purchaseAttemptSchema, body);
    if (!validation.success) {
      return createAuthResponse({ 
        error: 'Invalid request data',
        details: validation.error
      }, 400);
    }

    const { 
      session_id,
      event_id,
      purchaser_email,
      purchaser_name,
      items,
      platform_fee,
      hold_minutes = 30 
    } = validation.data;

    // Sanitize inputs
    const sanitizedData = {
      session_id: sanitizeString(session_id),
      event_id,
      purchaser_email: sanitizeEmail(purchaser_email),
      purchaser_name: sanitizeString(purchaser_name),
      items,
      platform_fee: platform_fee || 0,
      hold_minutes
    };

    // Calculate total amount
    const total_amount = sanitizedData.items.reduce((sum, item) => sum + (item.quantity * item.unit_price), 0);
    const expires_at = new Date(Date.now() + (sanitizedData.hold_minutes * 60 * 1000)).toISOString();

    // Create purchase attempt
    const { data: purchaseAttempt, error: purchaseError } = await supabase
      .from('purchase_attempts')
      .insert({
        session_id: sanitizedData.session_id,
        event_id: sanitizedData.event_id,
        purchaser_email: sanitizedData.purchaser_email,
        purchaser_name: sanitizedData.purchaser_name,
        total_amount,
        platform_fee: sanitizedData.platform_fee,
        expires_at,
        status: 'pending'
      })
      .select()
      .single();

    if (purchaseError) {
      throw purchaseError;
    }

    // Reserve tickets for each item
    const reservations = [];
    const purchaseItems = [];

    for (const item of sanitizedData.items) {
      try {
        // Reserve tickets
        const { data: reservationId, error: reserveError } = await supabase
          .rpc('reserve_tickets', {
            p_ticket_type_id: item.ticket_type_id,
            p_quantity: item.quantity,
            p_reserved_by: sanitizedData.session_id,
            p_hold_minutes: sanitizedData.hold_minutes,
            p_seat_ids: item.seat_id ? [item.seat_id] : null
          });

        if (reserveError) {
          throw reserveError;
        }

        reservations.push(reservationId);

        // Create purchase attempt item
        const { data: purchaseItem, error: itemError } = await supabase
          .from('purchase_attempt_items')
          .insert({
            purchase_attempt_id: purchaseAttempt.id,
            ticket_type_id: item.ticket_type_id,
            seat_id: item.seat_id || null,
            quantity: item.quantity,
            unit_price: item.unit_price,
            total_price: item.quantity * item.unit_price
          })
          .select()
          .single();

        if (itemError) {
          throw itemError;
        }

        purchaseItems.push(purchaseItem);

        // Link reservation to purchase attempt
        await supabase
          .from('ticket_reservations')
          .update({ reserved_for_purchase_id: purchaseAttempt.id })
          .eq('id', reservationId);

      } catch (itemError) {
        // If any item fails, clean up previous reservations
        for (const prevReservationId of reservations) {
          await supabase
            .from('ticket_reservations')
            .update({ status: 'cancelled' })
            .eq('id', prevReservationId);
        }

        // Mark purchase attempt as failed
        await supabase
          .from('purchase_attempts')
          .update({ 
            status: 'failed', 
            failure_reason: `Failed to reserve tickets: ${itemError instanceof Error ? itemError.message : 'Unknown error'}` 
          })
          .eq('id', purchaseAttempt.id);

        throw itemError;
      }
    }

    return createAuthResponse({
      success: true,
      purchase_attempt: {
        id: purchaseAttempt.id,
        session_id: purchaseAttempt.session_id,
        total_amount: purchaseAttempt.total_amount,
        platform_fee: purchaseAttempt.platform_fee,
        expires_at: purchaseAttempt.expires_at,
        status: purchaseAttempt.status,
        items: purchaseItems,
        reservations
      }
    });
  } catch (error) {
    // Log error for debugging
    console.error('Failed to create purchase attempt:', error);
    return createAuthResponse({ 
      error: 'Failed to create purchase attempt'
      // Don't expose internal error details in production
    }, 500);
  }
};