export const prerender = false;

import type { APIRoute } from 'astro';
import Stripe from 'stripe';
import { supabase } from '../../../lib/supabase';
import { sendTicketConfirmationEmail, sendOrderConfirmationEmail, sendOrganizerNotificationEmail } from '../../../lib/email';
import { logPaymentEvent } from '../../../lib/logger';

// Initialize Stripe with the secret key
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2024-06-20'
});

const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET!;

if (!endpointSecret) {
  throw new Error('Missing STRIPE_WEBHOOK_SECRET environment variable');
}

export const POST: APIRoute = async ({ request }) => {
  try {
    const body = await request.text();
    const signature = request.headers.get('stripe-signature');

    if (!signature) {
      console.error('Missing Stripe signature header');
      return new Response('Missing signature', { status: 400 });
    }

    let event: Stripe.Event;

    try {
      // Verify the webhook signature
      event = stripe.webhooks.constructEvent(body, signature, endpointSecret);
    } catch (err) {
      console.error('Webhook signature verification failed:', err);
      return new Response(`Webhook Error: ${err.message}`, { status: 400 });
    }

    // Handle the event
    switch (event.type) {
      case 'payment_intent.succeeded':
        await handlePaymentSucceeded(event.data.object as Stripe.PaymentIntent);
        break;
        
      case 'payment_intent.payment_failed':
        await handlePaymentFailed(event.data.object as Stripe.PaymentIntent);
        break;
        
      case 'charge.dispute.created':
        await handleChargeDispute(event.data.object as Stripe.Dispute);
        break;
        
      case 'account.updated':
        await handleAccountUpdated(event.data.object as Stripe.Account);
        break;
        
      default:
        console.log(`Unhandled event type: ${event.type}`);
    }

    return new Response('OK', { status: 200 });
  } catch (error) {
    console.error('Webhook handler error:', error);
    return new Response('Internal Server Error', { status: 500 });
  }
};

async function handlePaymentSucceeded(paymentIntent: Stripe.PaymentIntent) {
  console.log('Payment succeeded:', paymentIntent.id);
  
  try {
    // Log payment event
    logPaymentEvent({
      type: 'payment_completed',
      amount: paymentIntent.amount,
      currency: paymentIntent.currency,
      paymentIntentId: paymentIntent.id
    });

    // Find the purchase attempt by payment intent ID
    const { data: purchaseAttempt, error: findError } = await supabase
      .from('purchase_attempts')
      .select(`
        *,
        events (
          title,
          venue,
          start_time,
          description,
          created_by,
          users (name, email)
        )
      `)
      .eq('stripe_payment_intent_id', paymentIntent.id)
      .single();

    if (findError || !purchaseAttempt) {
      console.error('Purchase attempt not found for payment intent:', paymentIntent.id);
      return;
    }

    // Update purchase attempt status
    const { error: updateError } = await supabase
      .from('purchase_attempts')
      .update({ 
        status: 'completed',
        completed_at: new Date().toISOString()
      })
      .eq('id', purchaseAttempt.id);

    if (updateError) {
      console.error('Error updating purchase attempt:', updateError);
      return;
    }

    // Create tickets for each item in the purchase
    const { data: purchaseItems, error: itemsError } = await supabase
      .from('purchase_attempt_items')
      .select(`
        *,
        ticket_types (name, description),
        seats (row, number)
      `)
      .eq('purchase_attempt_id', purchaseAttempt.id);

    if (itemsError || !purchaseItems) {
      console.error('Error fetching purchase items:', itemsError);
      return;
    }

    const tickets = [];
    const orderTickets = [];

    for (const item of purchaseItems) {
      for (let i = 0; i < item.quantity; i++) {
        const { data: ticket, error: ticketError } = await supabase
          .from('tickets')
          .insert({
            event_id: purchaseAttempt.event_id,
            ticket_type_id: item.ticket_type_id,
            seat_id: item.seat_id,
            price: item.unit_price,
            purchaser_email: purchaseAttempt.purchaser_email,
            purchaser_name: purchaseAttempt.purchaser_name,
            purchase_attempt_id: purchaseAttempt.id,
            stripe_payment_intent_id: paymentIntent.id,
            status: 'valid'
          })
          .select()
          .single();

        if (ticketError) {
          console.error('Error creating ticket:', ticketError);
          continue;
        }

        tickets.push(ticket);

        // Send individual ticket confirmation email
        try {
          await sendTicketConfirmationEmail({
            ticketId: ticket.id,
            ticketUuid: ticket.uuid,
            eventTitle: purchaseAttempt.events.title,
            eventVenue: purchaseAttempt.events.venue,
            eventDate: new Date(purchaseAttempt.events.start_time).toLocaleDateString(),
            eventTime: new Date(purchaseAttempt.events.start_time).toLocaleTimeString(),
            ticketType: item.ticket_types.name,
            seatInfo: item.seats ? `Row ${item.seats.row}, Seat ${item.seats.number}` : undefined,
            price: item.unit_price,
            purchaserName: purchaseAttempt.purchaser_name,
            purchaserEmail: purchaseAttempt.purchaser_email,
            organizerName: purchaseAttempt.events.users.name,
            organizerEmail: purchaseAttempt.events.users.email,
            qrCodeUrl: '', // Will be generated in email function
            orderNumber: purchaseAttempt.id,
            totalAmount: purchaseAttempt.total_amount,
            platformFee: purchaseAttempt.platform_fee,
            eventDescription: purchaseAttempt.events.description,
            additionalInfo: 'Please arrive 15 minutes early for entry.'
          });
        } catch (emailError) {
          console.error('Error sending ticket confirmation email:', emailError);
        }
      }

      // Add to order summary
      orderTickets.push({
        type: item.ticket_types.name,
        quantity: item.quantity,
        price: item.unit_price,
        seatInfo: item.seats ? `Row ${item.seats.row}, Seat ${item.seats.number}` : undefined
      });
    }

    // Send order confirmation email
    try {
      await sendOrderConfirmationEmail({
        orderNumber: purchaseAttempt.id,
        purchaserName: purchaseAttempt.purchaser_name,
        purchaserEmail: purchaseAttempt.purchaser_email,
        eventTitle: purchaseAttempt.events.title,
        eventVenue: purchaseAttempt.events.venue,
        eventDate: new Date(purchaseAttempt.events.start_time).toLocaleDateString(),
        totalAmount: purchaseAttempt.total_amount,
        platformFee: purchaseAttempt.platform_fee,
        tickets: orderTickets,
        organizerName: purchaseAttempt.events.users.name,
        refundPolicy: 'Refunds available up to 24 hours before the event.'
      });
    } catch (emailError) {
      console.error('Error sending order confirmation email:', emailError);
    }

    // Send organizer notification
    try {
      await sendOrganizerNotificationEmail({
        organizerEmail: purchaseAttempt.events.users.email,
        organizerName: purchaseAttempt.events.users.name,
        eventTitle: purchaseAttempt.events.title,
        purchaserName: purchaseAttempt.purchaser_name,
        purchaserEmail: purchaseAttempt.purchaser_email,
        ticketType: orderTickets.map(t => `${t.quantity}x ${t.type}`).join(', '),
        amount: purchaseAttempt.total_amount - purchaseAttempt.platform_fee,
        orderNumber: purchaseAttempt.id
      });
    } catch (emailError) {
      console.error('Error sending organizer notification email:', emailError);
    }

    console.log(`Created ${tickets.length} tickets and sent confirmation emails for payment ${paymentIntent.id}`);
    
  } catch (error) {
    console.error('Error processing successful payment:', error);
    
    // Log payment error
    logPaymentEvent({
      type: 'payment_failed',
      amount: paymentIntent.amount,
      currency: paymentIntent.currency,
      paymentIntentId: paymentIntent.id,
      error: error.message
    });
  }
}

async function handlePaymentFailed(paymentIntent: Stripe.PaymentIntent) {
  console.log('Payment failed:', paymentIntent.id);
  
  try {
    // Update purchase attempt status
    const { error } = await supabase
      .from('purchase_attempts')
      .update({ 
        status: 'failed',
        failure_reason: 'Payment failed'
      })
      .eq('stripe_payment_intent_id', paymentIntent.id);

    if (error) {
      console.error('Error updating failed purchase attempt:', error);
    }

    // Release any reserved tickets
    const { error: releaseError } = await supabase
      .rpc('release_reservations_by_payment_intent', {
        p_payment_intent_id: paymentIntent.id
      });

    if (releaseError) {
      console.error('Error releasing reservations:', releaseError);
    }
    
  } catch (error) {
    console.error('Error processing failed payment:', error);
  }
}

async function handleChargeDispute(dispute: Stripe.Dispute) {
  console.log('Charge dispute created:', dispute.id);
  
  try {
    // Log the dispute for manual review
    await supabase
      .from('audit_logs')
      .insert({
        action: 'dispute_created',
        resource_type: 'charge',
        resource_id: dispute.charge as string,
        old_values: null,
        new_values: {
          dispute_id: dispute.id,
          amount: dispute.amount,
          reason: dispute.reason,
          status: dispute.status
        },
        ip_address: null,
        user_agent: 'stripe-webhook'
      });
      
    // TODO: Send alert to admin team
    
  } catch (error) {
    console.error('Error processing dispute:', error);
  }
}

async function handleAccountUpdated(account: Stripe.Account) {
  console.log('Stripe Connect account updated:', account.id);
  
  try {
    // Update organization with latest account status
    const { error } = await supabase
      .from('organizations')
      .update({
        stripe_account_status: account.charges_enabled ? 'active' : 'pending'
      })
      .eq('stripe_account_id', account.id);

    if (error) {
      console.error('Error updating organization account status:', error);
    }
    
  } catch (error) {
    console.error('Error processing account update:', error);
  }
}