/**
 * POST /api/payment-intent
 * Create or reuse Stripe PaymentIntent
 */

import { type NextRequest, NextResponse } from "next/server"
import { Security } from "@/lib/security"
import { WooCommerce } from "@/lib/woo"
import { StripeClient } from "@/lib/stripe"
import { PaymentIntentSchema } from "@/lib/schemas"
import { logger } from "@/lib/logger"
import { RateLimit, getClientIp } from "@/lib/rate-limit"

// Rate limit: 10 requests per minute per IP (stricter for payment creation)
const rateLimiter = new RateLimit(10, 60000)

export async function POST(request: NextRequest) {
  console.log("\n[v0] === PAYMENT INTENT REQUEST START ===")
  try {
    // Apply rate limiting
    const clientIp = getClientIp(request)
    const rateLimit = rateLimiter.check(clientIp)
    console.log("[v0] Client IP:", clientIp)
    console.log("[v0] Rate limit check:", rateLimit)
    
    if (!rateLimit.allowed) {
      return NextResponse.json(
        { error: "Too many requests. Please try again later." },
        { 
          status: 429,
          headers: {
            'X-RateLimit-Limit': '10',
            'X-RateLimit-Remaining': '0',
            'X-RateLimit-Reset': new Date(rateLimit.resetTime).toISOString(),
          }
        }
      )
    }

    // Validate origin (CORS)
    Security.validateOrigin(request)

    // Parse request body
    const body = await request.json()
    console.log("[v0] Request body received:", {
      hasToken: !!body.token,
      hasBillingAddress: !!body.billing_address,
      hasShippingAddress: !!body.shipping_address,
      tokenPreview: body.token ? body.token.substring(0, 20) + "..." : "missing",
    })

    // Validate request
    const validation = PaymentIntentSchema.safeParse(body)
    if (!validation.success) {
      logger.error("v0", "Payment intent validation failed", {
        body,
        errors: validation.error.issues,
        errorDetails: validation.error.flatten(),
      })
      console.error("[v0] Payment Intent Validation Error:")
      console.error("Request body:", JSON.stringify(body, null, 2))
      console.error("Validation errors:", JSON.stringify(validation.error.issues, null, 2))
      return NextResponse.json({ error: "Invalid request", details: validation.error.issues }, { status: 400 })
    }

    const { token, billing_address, shipping_address } = validation.data

    // Verify token and get order context
    let context
    try {
      context = await Security.verifyToken(token)
      logger.info("v0", "Token verified successfully", {
        orderId: context.orderId,
      })
    } catch (error) {
      logger.error("v0", "Token verification failed", {
        token: token.substring(0, 20) + "...",
        error: error instanceof Error ? error.message : "Unknown error",
      })
      console.error("[v0] Token Verification Error:", error)
      throw error
    }

    // Fetch order from WooCommerce
    let order
    try {
      order = await WooCommerce.getOrder(context.orderId)
      logger.info("v0", "Order fetched successfully", {
        orderId: order.id,
        status: order.status,
        total: order.total,
        customerId: order.customer_id,
      })
      console.log("[v0] Order Details:", {
        id: order.id,
        status: order.status,
        total: order.total,
        currency: order.currency,
        customer_id: order.customer_id,
      })
    } catch (error) {
      logger.error("v0", "Failed to fetch order from WooCommerce", {
        orderId: context.orderId,
        error: error instanceof Error ? error.message : "Unknown error",
      })
      console.error("[v0] WooCommerce Order Fetch Error:", error)
      throw error
    }

    // Check if order can be paid
    if (!WooCommerce.canBePaid(order)) {
      logger.error("v0", "Order cannot be paid", {
        orderId: order.id,
        status: order.status,
        isPaid: WooCommerce.isPaid(order),
      })
      console.error("[v0] Order Status Error:", {
        orderId: order.id,
        currentStatus: order.status,
        canBePaid: WooCommerce.canBePaid(order),
        isPaid: WooCommerce.isPaid(order),
      })
      return NextResponse.json({ 
        error: "Order cannot be paid", 
        details: {
          orderId: order.id,
          status: order.status,
          reason: WooCommerce.isPaid(order) ? "Order is already paid" : "Order status is not pending"
        }
      }, { status: 400 })
    }

    // Normalize order to get amount (SERVER ONLY - never trust frontend)
    const normalizedOrder = WooCommerce.normalize(order)

    logger.info("v0", "Order pricing breakdown", {
      orderId: order.id,
      subtotal_cents: normalizedOrder.subtotal_cents,
      tax_cents: normalizedOrder.tax_cents,
      shipping_cost_cents: normalizedOrder.shipping_cost_cents,
      total_cents: normalizedOrder.total_cents,
      woo_original_total: order.total,
    })

    const pricingMetadata = {
      subtotal_cents: normalizedOrder.subtotal_cents.toString(),
      tax_cents: normalizedOrder.tax_cents.toString(),
      shipping_cents: normalizedOrder.shipping_cost_cents.toString(),
    }

    // Check if PaymentIntent already exists
    let paymentIntent
    if (normalizedOrder.payment_intent_id) {
      paymentIntent = await StripeClient.getPaymentIntent(normalizedOrder.payment_intent_id)

      // If the stored PaymentIntent has a different amount (e.g., created before
      // tax/shipping fix), update it to match the correct total.
      if (paymentIntent.amount !== normalizedOrder.total_cents &&
          paymentIntent.status === "requires_payment_method") {
        const stripe = StripeClient.getClient()
        paymentIntent = await stripe.paymentIntents.update(paymentIntent.id, {
          amount: normalizedOrder.total_cents,
          metadata: {
            wc_order_id: order.id.toString(),
            ...pricingMetadata,
          },
        })
        logger.info("v0", "Updated existing PaymentIntent amount", {
          orderId: order.id,
          oldAmount: paymentIntent.amount,
          newAmount: normalizedOrder.total_cents,
        })
      }
    } else {
      // Create new PaymentIntent with full pricing breakdown in metadata
      paymentIntent = await StripeClient.createOrGetPaymentIntent({
        orderId: order.id,
        amountCents: normalizedOrder.total_cents,
        currency: normalizedOrder.currency,
        email: normalizedOrder.email,
        description: `Order #${order.id}`,
        metadata: pricingMetadata,
      })

      // Store PaymentIntent ID in WooCommerce
      const metaData = WooCommerce.setMeta(order, "_payment_intent_id", paymentIntent.id)
      await WooCommerce.updateOrder(order.id, { meta_data: metaData })
    }

    // Update addresses if provided
    if (billing_address || shipping_address) {
      const updateData: any = {}

      if (billing_address) {
        updateData.billing = WooCommerce.toWooAddress(billing_address)
        // Also set billing email if provided
        if (billing_address.first_name || billing_address.last_name) {
          updateData.billing_email = normalizedOrder.email
        }
        
        // If shipping_address is null, use billing address for shipping (same as billing)
        if (shipping_address === null) {
          updateData.shipping = WooCommerce.toWooAddress(billing_address)
          console.log("[v0] Using billing address for shipping (same as billing)")
        }
      }

      if (shipping_address) {
        updateData.shipping = WooCommerce.toWooAddress(shipping_address)
        console.log("[v0] Using separate shipping address")
      }

      // Add metadata to track that addresses were updated via checkout
      const addressMetadata = [
        ...order.meta_data,
        {
          key: "_checkout_address_updated",
          value: new Date().toISOString(),
        },
      ]
      updateData.meta_data = addressMetadata

      console.log("[v0] Updating order addresses:", {
        hasBilling: !!updateData.billing,
        hasShipping: !!updateData.shipping,
        shippingSameAsBilling: shipping_address === null,
      })

      await WooCommerce.updateOrder(order.id, updateData)
    }

    // Don't mark nonce as used yet - allow retries until payment succeeds
    // Nonce will be validated but not consumed until webhook confirms payment

    return NextResponse.json({
      success: true,
      client_secret: paymentIntent.client_secret,
      payment_intent_id: paymentIntent.id,
    })
  } catch (error) {
    logger.error("v0", "Payment intent error", {
      error: error instanceof Error ? error.message : "Unknown error",
      stack: error instanceof Error ? error.stack : undefined,
    })
    
    // Enhanced console logging for debugging
    console.error("\n=== [v0] PAYMENT INTENT ERROR ===")
    console.error("Error Type:", error instanceof Error ? error.constructor.name : typeof error)
    console.error("Error Message:", error instanceof Error ? error.message : String(error))
    if (error instanceof Error && error.stack) {
      console.error("Stack Trace:", error.stack)
    }
    console.error("================================\n")
    
    return NextResponse.json(
      {
        success: false,
        error: {
          code: "PAYMENT_INTENT_ERROR",
          message: error instanceof Error ? error.message : "Failed to create payment intent",
          details: process.env.NODE_ENV === "development" ? error : undefined,
        },
      },
      { status: 500 },
    )
  }
}
