import { NextRequest, NextResponse } from 'next/server';
import { headers } from 'next/headers';
import Stripe from 'stripe';
import { stripe } from '@/lib/stripe';
import { prisma } from '@/lib/prisma';

// Disable body parsing for webhooks
export const runtime = 'nodejs';

export async function POST(request: NextRequest) {
  try {
    const body = await request.text();
    const headersList = await headers();
    const signature = headersList.get('stripe-signature');

    if (!signature) {
      console.error('No stripe-signature header found');
      return NextResponse.json(
        { error: 'No stripe-signature header found' },
        { status: 400 }
      );
    }

    let event: Stripe.Event;

    try {
      event = stripe.webhooks.constructEvent(
        body,
        signature,
        process.env.STRIPE_WEBHOOK_SECRET!
      );
    } catch (err: any) {
      console.error('Webhook signature verification failed:', err.message);
      return NextResponse.json(
        { error: 'Webhook signature verification failed' },
        { status: 400 }
      );
    }

    console.log('Received Stripe webhook event:', event.type, event.id);

    // Handle the event
    switch (event.type) {
      case 'payment_intent.succeeded':
        await handlePaymentIntentSucceeded(event.data.object as Stripe.PaymentIntent);
        break;

      case 'payment_intent.payment_failed':
        await handlePaymentIntentFailed(event.data.object as Stripe.PaymentIntent);
        break;

      case 'payment_intent.processing':
        await handlePaymentIntentProcessing(event.data.object as Stripe.PaymentIntent);
        break;

      case 'payment_intent.requires_action':
        await handlePaymentIntentRequiresAction(event.data.object as Stripe.PaymentIntent);
        break;

      case 'payment_intent.canceled':
        await handlePaymentIntentCanceled(event.data.object as Stripe.PaymentIntent);
        break;

      case 'customer.created':
        await handleCustomerCreated(event.data.object as Stripe.Customer);
        break;

      case 'invoice.payment_succeeded':
        // For future subscription renewals
        console.log('Invoice payment succeeded:', event.data.object.id);
        break;

      case 'invoice.payment_failed':
        // For future subscription payment failures
        console.log('Invoice payment failed:', event.data.object.id);
        break;

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

    return NextResponse.json({ received: true });
  } catch (error: any) {
    console.error('Webhook processing error:', {
      error: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString()
    });
    
    return NextResponse.json(
      { 
        error: 'Webhook processing failed',
        message: 'An error occurred while processing the webhook',
        timestamp: new Date().toISOString(),
        details: process.env.NODE_ENV === 'development' ? error.message : undefined
      },
      { status: 500 }
    );
  }
}

async function handlePaymentIntentSucceeded(paymentIntent: Stripe.PaymentIntent) {
  console.log('--- Handling Payment Intent Succeeded ---');
  console.log('Received payment intent object:', JSON.stringify(paymentIntent, null, 2));

  try {
    console.log('🚀 [WEBHOOK] Payment succeeded:', paymentIntent.id);
    console.log('🚀 [WEBHOOK] Payment metadata:', JSON.stringify(paymentIntent.metadata, null, 2));

    // Get user ID from payment metadata
    const userId = paymentIntent.metadata?.userId;
    const categoryIds = paymentIntent.metadata?.categoryIds?.split(',') || [];

    console.log('🔍 [WEBHOOK] Extracted from metadata - userId:', userId, 'categoryIds:', categoryIds);

    if (!userId) {
      console.error('❌ [WEBHOOK] No userId found in payment intent metadata. Aborting.');
      return;
    }

    if (!categoryIds.length) {
      console.error('❌ [WEBHOOK] No categoryIds found in payment intent metadata. Aborting.');
      return;
    }

    // Activate subscriptions for purchased categories
    const currentDate = new Date();
    const expirationDate = new Date(currentDate.getTime() + 30 * 24 * 60 * 60 * 1000); // 30 days

    console.log('🔄 [WEBHOOK] Preparing to create/update subscriptions for categories:', categoryIds);
    console.log('📅 [WEBHOOK] Subscription dates - Start:', currentDate.toISOString(), 'End:', expirationDate.toISOString());

    let subscriptionsCreated = 0;
    let subscriptionsUpdated = 0;

    for (const categoryId of categoryIds) {
      try {
        console.log(`🔍 [WEBHOOK] Processing category: ${categoryId}`);
        
        // Check if subscription already exists
        console.log(`--- Checking for existing subscription for userId: ${userId}, categoryId: ${categoryId} ---`);
        const existingSubscription = await prisma.categorySubscription.findFirst({
          where: {
            userId,
            categoryId,
          },
        });

        if (existingSubscription) {
          console.log(`--- Found existing subscription. Updating... ---`);
          console.log(`🔄 [WEBHOOK] Updating existing subscription for category ${categoryId}, subscription ID: ${existingSubscription.id}`);
          
          await prisma.categorySubscription.update({
            where: { id: existingSubscription.id },
            data: {
              status: 'ACTIVE',
              endDate: expirationDate,
              updatedAt: currentDate,
            },
          });
          
          subscriptionsUpdated++;
          console.log(`✅ [WEBHOOK] Successfully updated subscription for category ${categoryId}`);
        } else {
          console.log(`--- No existing subscription found. Creating new one... ---`);
          console.log(`🆕 [WEBHOOK] Creating new subscription for category ${categoryId}`);
          
          const newSubscription = await prisma.categorySubscription.create({
            data: {
              userId,
              categoryId,
              status: 'ACTIVE',
              startDate: currentDate,
              endDate: expirationDate,
            },
          });
          
          subscriptionsCreated++;
          console.log(`✅ [WEBHOOK] Successfully created new subscription for category ${categoryId}, subscription ID: ${newSubscription.id}`);
        }
      } catch (subscriptionError: any) {
        console.error(`❌ [WEBHOOK] Error processing subscription for category ${categoryId}:`, subscriptionError.message);
        console.error(`Error details:`, {
          userId,
          categoryId,
          errorMessage: subscriptionError.message,
          errorStack: subscriptionError.stack,
        });
      }
    }

    console.log(`📊 [WEBHOOK] Subscription processing complete. Created: ${subscriptionsCreated}, Updated: ${subscriptionsUpdated}`);

    // Verify subscriptions and send notification
    console.log('--- Verifying all active subscriptions for user ---');
    const allActiveSubscriptions = await prisma.categorySubscription.findMany({
      where: {
        userId,
        status: 'ACTIVE',
        endDate: { gte: new Date() }
      },
      include: {
        category: { select: { name: true } }
      }
    });

    console.log(`✅ [WEBHOOK] User ${userId} now has ${allActiveSubscriptions.length} active subscriptions:`, 
      allActiveSubscriptions.map(s => s.category.name).join(', '));

    console.log('--- Creating success notification ---');
    try {
      await prisma.notification.create({
        data: {
          userId,
          type: 'subscription_purchased',
          title: 'Payment Successful',
          message: `Your membership payment of ${(paymentIntent.amount / 100).toFixed(2)} ${paymentIntent.currency.toUpperCase()} has been processed successfully.`,
          data: JSON.stringify({
            paymentIntentId: paymentIntent.id,
            amount: paymentIntent.amount / 100,
            currency: paymentIntent.currency,
            categoryIds,
          }),
        },
      });
      console.log('✅ [WEBHOOK] Successfully created success notification.');
    } catch (notificationError: any) {
      console.error('❌ [WEBHOOK] Error creating success notification:', notificationError.message);
    }

    console.log('--- Payment processing completed successfully ---');
  } catch (error: any) {
    console.error('❌ [WEBHOOK] Critical error in handlePaymentIntentSucceeded:', error.message);
    console.error('Full error object:', error);
  }
}

async function handlePaymentIntentFailed(paymentIntent: Stripe.PaymentIntent) {
  try {
    console.log('Payment failed:', paymentIntent.id);

    // Update payment record
    try {
      const existingPayment = await prisma.payment.findUnique({
        where: { paymentIntentId: paymentIntent.id },
      });
      if (existingPayment) {
        await prisma.payment.update({
          where: { paymentIntentId: paymentIntent.id },
          data: { status: 'FAILED', updatedAt: new Date() },
        });
      }
    } catch (paymentUpdateErr) {
      console.error('Skipping payment record update (not found or other issue):', paymentUpdateErr);
    }

    // Get user ID from metadata
    const userId = paymentIntent.metadata?.userId;

    if (!userId) {
      console.error('No userId found in payment intent metadata');
      return;
    }

    // Send failure notification
    try {
      await prisma.notification.create({
        data: {
          userId,
          type: 'payment_failed',
          title: 'Payment Failed',
          message: `Your membership payment of ${(paymentIntent.amount / 100).toFixed(2)} ${paymentIntent.currency.toUpperCase()} failed. Please try again.`,
          data: JSON.stringify({
            paymentIntentId: paymentIntent.id,
            amount: paymentIntent.amount / 100,
            currency: paymentIntent.currency,
            lastPaymentError: paymentIntent.last_payment_error?.message,
          }),
        },
      });
    } catch (notificationError) {
      console.error('Error creating failure notification:', notificationError);
    }

    console.log('Payment failure processed for user:', userId);
  } catch (error) {
    console.error('Error handling payment failure:', error);
  }
}

async function handlePaymentIntentProcessing(paymentIntent: Stripe.PaymentIntent) {
  try {
    console.log('Payment processing:', paymentIntent.id);

    // Update payment record
    try {
      const existingPayment = await prisma.payment.findUnique({
        where: { paymentIntentId: paymentIntent.id },
      });
      if (existingPayment) {
        await prisma.payment.update({
          where: { paymentIntentId: paymentIntent.id },
          data: { status: 'PENDING', updatedAt: new Date() },
        });
      }
    } catch (paymentUpdateErr) {
      console.error('Skipping payment record update (not found or other issue):', paymentUpdateErr);
    }
  } catch (error) {
    console.error('Error handling payment processing:', error);
  }
}

async function handlePaymentIntentRequiresAction(paymentIntent: Stripe.PaymentIntent) {
  try {
    console.log('Payment requires action:', paymentIntent.id);
    // Payment requires additional authentication (3D Secure)
    // The client will handle this
  } catch (error) {
    console.error('Error handling payment requires action:', error);
  }
}

async function handlePaymentIntentCanceled(paymentIntent: Stripe.PaymentIntent) {
  try {
    console.log('Payment canceled:', paymentIntent.id);

    // Update payment record
    try {
      const existingPayment = await prisma.payment.findUnique({
        where: { paymentIntentId: paymentIntent.id },
      });
      if (existingPayment) {
        await prisma.payment.update({
          where: { paymentIntentId: paymentIntent.id },
          data: { status: 'FAILED', updatedAt: new Date() },
        });
      }
    } catch (paymentUpdateErr) {
      console.error('Skipping payment record update (not found or other issue):', paymentUpdateErr);
    }
  } catch (error) {
    console.error('Error handling payment cancellation:', error);
  }
}

async function handleCustomerCreated(customer: Stripe.Customer) {
  try {
    console.log('Customer created:', customer.id);
    // Handle customer creation if needed
    // For now, we're not storing Stripe customer IDs in our database
    // but this could be useful for future subscription management
  } catch (error) {
    console.error('Error handling customer creation:', error);
  }
}