import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { stripe, createPaymentIntent, findCustomerByEmail, createCustomer } from '@/lib/stripe';

interface PurchaseRequest {
  categoryIds: string[];
  amount?: number;
  currency?: string;
  country?: string;
  billingName?: string;
  addressLine1?: string;
  city?: string;
  postalCode?: string;
  state?: string;
}

export async function POST(req: NextRequest) {
  try {
    const session = await getServerSession(authOptions);
    
    if (!session?.user?.id || !session?.user?.email) {
      return NextResponse.json(
        { 
          error: 'Authentication required',
          message: 'You must be logged in to purchase a membership. Please sign in and try again.',
          action: 'redirect_login'
        },
        { status: 401 }
      );
    }

    const body: PurchaseRequest = await req.json();
    const { 
      categoryIds, 
      amount, 
      currency = 'EUR', 
      country = 'LU',
      billingName,
      addressLine1,
      city,
      postalCode,
      state
    } = body;

    if (!categoryIds || !Array.isArray(categoryIds) || categoryIds.length === 0) {
      return NextResponse.json(
        { 
          error: 'Category selection required',
          message: 'Please select at least one category for your membership subscription. You can choose from our available service categories.',
          details: 'No categories provided in the request'
        },
        { status: 400 }
      );
    }

    if (!prisma) {
      return NextResponse.json(
        { 
          error: 'Service unavailable',
          message: 'Database service is currently unavailable. Please try again later.'
        },
        { status: 503 }
      );
    }

    try {
      // Calculate amount based on country
      let calculatedAmount = amount;
      if (!calculatedAmount) {
        const basePrice = country.toUpperCase() === 'CH' ? 19.90 : 9.90; // CHF 19.90 for Switzerland, EUR 9.90 for others
        calculatedAmount = categoryIds.length * basePrice;
      }

      // Validate categories exist
      const categories = await prisma.category.findMany({
        where: {
          id: { in: categoryIds }
        }
      });

      if (categories.length !== categoryIds.length) {
        const validCategoryIds = categories.map(c => c.id);
        const invalidCategoryIds = categoryIds.filter(id => !validCategoryIds.includes(id));
        return NextResponse.json(
          { 
            error: 'Invalid categories selected',
            message: `Some of the categories you selected are no longer available. Please refresh the page and select valid categories.`,
            details: `Invalid category IDs: ${invalidCategoryIds.join(', ')}`,
            validCategories: categories.map(c => ({ id: c.id, name: c.name }))
          },
          { status: 400 }
        );
      }

      // Check for existing active subscriptions
      const existingSubscriptions = await prisma.categorySubscription.findMany({
        where: {
          userId: session.user.id,
          categoryId: { in: categoryIds },
          status: 'ACTIVE',
          endDate: { gte: new Date() }
        },
        include: {
          category: {
            select: { name: true }
          }
        }
      });

      if (existingSubscriptions.length > 0) {
        const activeCategories = existingSubscriptions.map(sub => sub.category.name);
        const earliestExpiry = new Date(Math.min(...existingSubscriptions.map(sub => new Date(sub.endDate).getTime())));
        return NextResponse.json(
          { 
            error: 'Active membership already exists',
            message: `You already have active memberships for: ${activeCategories.join(', ')}. These memberships will expire on ${earliestExpiry.toLocaleDateString()}.`,
            details: 'Cannot purchase duplicate memberships while active ones exist',
            activeSubscriptions: existingSubscriptions.map(sub => ({
              category: sub.category.name,
              expiryDate: sub.endDate
            }))
          },
          { status: 409 }
        );
      }

      // Ensure we have user profile info to populate required customer name/address
      const user = await prisma.user.findUnique({
        where: { email: session.user.email },
        include: { profile: true }
      });

      const customerName = billingName 
        || (user?.profile 
          ? `${user.profile.firstName || ''} ${user.profile.lastName || ''}`.trim()
          : session.user.name || undefined);

      const inferredCountry = (country || user?.profile?.countryId || '').toString().slice(0, 2).toUpperCase();
      const customerAddress = {
        line1: addressLine1 || user?.profile?.address || undefined,
        city: city || user?.profile?.city || undefined,
        postal_code: postalCode || (user?.profile as any)?.zipCode || undefined,
        state: state || undefined,
        country: inferredCountry || undefined,
      };

      // Validate presence of name and address for export compliance
      const missing: string[] = [];
      if (!customerName) missing.push('name');
      if (!customerAddress.line1) missing.push('address line1');
      if (!customerAddress.city) missing.push('city');
      if (!customerAddress.country) missing.push('country');
      if (missing.length > 0) {
        return NextResponse.json(
          {
            error: 'Customer information required',
            message: 'As per Indian regulations, export transactions require a customer name and address.',
            code: 'REQUIRES_CUSTOMER_DETAILS',
            missingFields: missing
          },
          { status: 400 }
        );
      }

      // Find or create Stripe customer with required details
      let customer = await findCustomerByEmail(session.user.email);
      if (!customer) {
        customer = await createCustomer(
          session.user.email,
          customerName,
          {
            userId: session.user.id,
            source: 'smile24_membership',
            country: country
          },
          customerAddress
        );
      } else if (customer) {
        // Ensure existing customer has required name and address for export compliance
        const hasAddr = !!((customer as any)?.address as any)?.line1 && !!((customer as any)?.address as any)?.country;
        if (!(customer as any).name || !hasAddr) {
          await stripe.customers.update((customer as any).id, {
            name: (customer as any).name || customerName,
            address: hasAddr ? undefined : customerAddress,
          } as any);
          customer = await stripe.customers.retrieve((customer as any).id) as any;
        }
      }

      if (!customer) {
        return NextResponse.json(
          {
            error: 'Customer creation failed',
            message: 'Unable to prepare customer details required for export transactions.'
          },
          { status: 500 }
        );
      }

      // Prepare shipping details for export regulations compliance
      const shipping = {
        name: (customer as any).name as string,
        address: {
          line1: ((customer as any).address as any)?.line1 as string,
          city: ((customer as any).address as any)?.city as string,
          postal_code: ((customer as any).address as any)?.postal_code as string,
          country: ((customer as any).address as any)?.country as string,
        }
      } as const;

      // Create Stripe Payment Intent with customer and shipping details
      const paymentIntent = await createPaymentIntent(
        calculatedAmount,
        currency,
        {
          userId: session.user.id,
          categoryIds: categoryIds.join(','),
          categoryNames: categories.map(cat => cat.name).join(', '),
          country,
          customerEmail: session.user.email,
          type: 'membership_subscription',
          subscriptionDuration: '30_days'
        },
        customer.id, // Pass customer ID for export regulations compliance
        shipping
      );

      // Note: Payment record will be created by webhook upon successful payment
      // For now, we just return the payment intent details

      return NextResponse.json({
        success: true,
        message: `Payment ready for ${categories.length} category membership${categories.length > 1 ? 's' : ''}: ${categories.map(cat => cat.name).join(', ')}`,
        data: {
          paymentIntentId: paymentIntent.id,
          clientSecret: paymentIntent.client_secret,
          // Return amount in actual value (not cents) as stripe.ts will handle conversion
          amount: calculatedAmount,
          currency: currency.toUpperCase(),
          categoryNames: categories.map(cat => cat.name),
          stripeCustomerId: customer.id,
          status: 'PENDING',
          totalAmount: calculatedAmount.toFixed(2),
          breakdown: {
            categoryCount: categories.length,
            pricePerCategory: country.toUpperCase() === 'CH' ? 19.90 : 9.90,
            currency: currency.toUpperCase()
          }
        }
      });

    } catch (dbError: any) {
      console.error('Database error during subscription purchase:', dbError);
      
      return NextResponse.json(
        { 
          error: 'Database connection error',
          message: 'We are experiencing temporary database issues. Your payment has not been charged. Please try again in a few minutes or contact support if the problem persists.',
          details: process.env.NODE_ENV === 'development' ? dbError.message : undefined,
          support: 'If this error continues, please contact our support team with the error code: DB_PURCHASE_001'
        },
        { status: 500 }
      );
    }

  } catch (error: any) {
    console.error('Error processing membership purchase:', error);
    
    let userMessage = 'An unexpected error occurred while setting up your membership purchase.';
    let errorCode = 'PURCHASE_001';
    
    // Provide more specific error messages based on error type
    if (error.type === 'StripeInvalidRequestError') {
      userMessage = 'There was an issue with the payment setup. Please check your payment details and try again.';
      errorCode = 'STRIPE_INVALID_001';
    } else if (error.type === 'StripeAPIError') {
      userMessage = 'Payment service is temporarily unavailable. Please try again in a few minutes.';
      errorCode = 'STRIPE_API_001';
    } else if (error.code === 'ECONNREFUSED') {
      userMessage = 'Unable to connect to payment services. Please check your internet connection and try again.';
      errorCode = 'CONNECTION_001';
    }
    
    return NextResponse.json(
      { 
        error: 'Payment setup failed',
        message: userMessage,
        details: process.env.NODE_ENV === 'development' ? error.message : undefined,
        errorCode,
        support: `If this error persists, please contact our support team with error code: ${errorCode}`
      },
      { status: 500 }
    );
  }
}