import { NextRequest, NextResponse } from "next/server"
import { prisma } from "@/lib/prisma"
import Stripe from "stripe"
import { sendOrderConfirmationEmail } from "@/lib/email"

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || "", {
  apiVersion: "2026-04-22.dahlia",
})

export async function POST(req: NextRequest) {
  try {
    const body = await req.json()
    const {
      fullName,
      email,
      phone,
      address,
      paymentMethod,
      totalAmount,
      items,
      paymentDetails,
      pointsRedeemed,
      promoCode,
    } = body

    if (!email || !fullName || !phone || !address || !items || items.length === 0) {
      return NextResponse.json(
        { message: "Missing required fields for order submission." },
        { status: 400 }
      )
    }

    // Fetch dynamic settings
    const settings = await prisma.setting.findMany()
    const settingsObj = settings.reduce((acc: Record<string, string>, setting) => {
      acc[setting.key] = setting.value
      return acc
    }, {})
    const earnRate = Number(settingsObj["reward_point_earn_rate"]) || 10

    // 1. Create or Find User
    let user = await prisma.user.findUnique({
      where: { email },
    })

    if (!user) {
      user = await prisma.user.create({
        data: {
          email,
          name: fullName,
          password: `GUEST_${Math.random().toString(36).slice(-8)}`,
          phone,
          role: "USER",
        },
      })
    }

    // 2. Run order creation inside an atomic transaction
    const order = await prisma.$transaction(async (tx) => {
      // Refetch user inside transaction to get latest rewardPoints and prevent race conditions
      const txUser = await tx.user.findUnique({
        where: { id: user.id },
      })

      if (!txUser) {
        throw new Error("User record not found.")
      }

      let pointsToDeduct = 0
      if (pointsRedeemed && pointsRedeemed > 0) {
        if (txUser.rewardPoints < pointsRedeemed) {
          throw new Error(`Insufficient reward points. Available: ${txUser.rewardPoints}`)
        }
        pointsToDeduct = pointsRedeemed
      }

      let calculatedTotal = 0;
      const orderItemsData = []

      for (const item of items) {
        // Find matching variant
        let variant = await tx.productVariant.findFirst({
          where: {
            productId: item.productId,
            color: item.color,
            size: item.size,
            length: item.length || null,
          },
          include: { product: true }
        })

        // Fallback: If exact variant is not found (e.g. slight metadata mismatch), find the first available variant for the product
        if (!variant) {
          variant = await tx.productVariant.findFirst({
            where: { productId: item.productId },
            include: { product: true }
          })
        }

        if (!variant) {
          throw new Error(`Product variant not found for ${item.title || item.productId}`)
        }

        // ✅ Stock validation — prevent oversell
        if (variant.stock < item.quantity) {
          throw new Error(`Insufficient stock for "${item.title || "item"}". Available: ${variant.stock}, Requested: ${item.quantity}`)
        }

        // Decrement product variant stock
        const newStock = variant.stock - item.quantity
        await tx.productVariant.update({
          where: { id: variant.id },
          data: { stock: newStock },
        })

        // Log inventory change
        await tx.inventoryLog.create({
          data: {
            variantId: variant.id,
            previousStock: variant.stock,
            newStock: newStock,
            note: `Stock reduced due to checkout purchase. Order placed by ${fullName}.`,
          },
        })

        // Calculate actual price
        const actualPrice = variant.price || variant.product.discountPrice || variant.product.basePrice;
        calculatedTotal += actualPrice * item.quantity;

        orderItemsData.push({
          variantId: variant.id,
          quantity: item.quantity,
          price: actualPrice,
        })
      }

      // Calculate subtotal
      let preTaxAmount = Math.max(0, calculatedTotal - pointsToDeduct);
      
      let appliedDiscount = 0;

      if (promoCode) {
        const coupon = await tx.coupon.findUnique({ where: { code: promoCode.toUpperCase() } });
        if (!coupon || !coupon.active) throw new Error("Invalid or inactive coupon code.");
        if (coupon.expiresAt && new Date() > coupon.expiresAt) throw new Error("This coupon has expired.");
        if (coupon.maxUses !== null && coupon.usedCount >= coupon.maxUses) throw new Error("This coupon has reached its usage limit.");
        if (coupon.minOrderAmount && calculatedTotal < coupon.minOrderAmount) throw new Error(`This coupon requires a minimum order of ৳${coupon.minOrderAmount.toFixed(0)}.`);
        
        if (coupon.type === "PERCENTAGE") {
          appliedDiscount = Math.min((calculatedTotal * coupon.discount) / 100, calculatedTotal);
        } else {
          appliedDiscount = Math.min(coupon.discount, calculatedTotal);
        }
        preTaxAmount = Math.max(0, preTaxAmount - appliedDiscount);

        // Update coupon usage
        await tx.coupon.update({
          where: { id: coupon.id },
          data: { usedCount: { increment: 1 } }
        });
      }
      
      // Calculate tax and shipping safely on the backend
      const tax = preTaxAmount * 0.05; // 5% Standard Tax
      const flatRate = Number(settingsObj["shipping_flat_rate"]) || 10;
      const freeThreshold = Number(settingsObj["shipping_free_threshold"]) || 150;
      const shippingEnabled = settingsObj["shipping_enabled"] !== "false";
      
      const shippingFee = shippingEnabled ? (freeThreshold > 0 && calculatedTotal >= freeThreshold ? 0 : flatRate) : 0;
      
      const finalPayableAmount = preTaxAmount + tax + shippingFee;
      
      // Calculate reward points earned from this real total
      const pointsEarned = Math.floor(finalPayableAmount / earnRate)

      // VERIFY STRIPE PAYMENT
      if (paymentMethod === "card" && finalPayableAmount > 0) {
        if (!paymentDetails?.paymentIntentId) {
          throw new Error("Missing Payment Intent ID for Card payment.");
        }
        
        const intent = await stripe.paymentIntents.retrieve(paymentDetails.paymentIntentId);
        
        if (intent.status !== "succeeded") {
          throw new Error(`Stripe payment not successful. Status: ${intent.status}`);
        }
        
        // Stripe uses cents, so multiply by 100
        const expectedAmountInCents = Math.round(finalPayableAmount * 100);
        if (intent.amount !== expectedAmountInCents) {
          throw new Error("Stripe payment amount mismatch. Possible tampering detected.");
        }
      }

      // Create main Order
      const newOrder = await tx.order.create({
        data: {
          userId: user.id,
          totalAmount: finalPayableAmount,
          status: "PENDING",
          paymentStatus: paymentMethod === "cod" ? "PENDING" : "PAID",
          shippingAddress: address,
          shippingPhone: phone,
          pointsRedeemed: pointsToDeduct,
          pointsEarned: pointsEarned,
          items: {
            create: orderItemsData,
          },
        },
      })

      // Atomically adjust user's reward points balance
      await tx.user.update({
        where: { id: user.id },
        data: {
          rewardPoints: {
            increment: pointsEarned - pointsToDeduct,
          },
        },
      })

      // If not Cash on Delivery, record Payment transaction details
      if (paymentMethod !== "cod") {
        const transactionId =
          paymentMethod === "bkash"
            ? paymentDetails?.bkashNumber || "BKASH_PAY"
            : paymentMethod === "nagad"
            ? paymentDetails?.nagadNumber || "NAGAD_PAY"
            : paymentMethod === "card"
            ? paymentDetails?.paymentIntentId || "STRIPE_PAY"
            : "OTHER_PAY"

        await tx.payment.create({
          data: {
            orderId: newOrder.id,
            provider: paymentMethod,
            amount: finalPayableAmount,
            status: "PAID",
            transactionId,
          },
        })
      }

      return newOrder
    })

    // Send order confirmation email (non-blocking)
    try {
      const orderItems = items.map((item: any) => ({
        title: item.title || "Product",
        quantity: item.quantity,
        price: item.price || 0,
        color: item.color,
        size: item.size,
      }))
      await sendOrderConfirmationEmail(email, {
        customerName: fullName,
        orderId: order.id,
        items: orderItems,
        totalAmount: order.totalAmount,
        shippingAddress: address,
        paymentMethod,
      })
    } catch (emailErr) {
      console.error("[CHECKOUT_EMAIL_ERROR]", emailErr)
    }

    return NextResponse.json({
      success: true,
      orderId: order.id,
    })
  } catch (error: any) {
    console.error("[CHECKOUT_POST_ERROR]", error)
    return NextResponse.json(
      { message: error.message || "Failed to process checkout order." },
      { status: 500 }
    )
  }
}
