import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { paymentProvider } from "@/lib/payments";
import { checkRateLimit } from "@/lib/rate-limit";
import { displayPrice, orderNumber } from "@/lib/utils";
import { checkoutSchema } from "@/lib/validations";

function paymentStatusMessage(status: string) {
  if (status === "FAILED") return "Payment could not be completed. Please retry checkout or contact support.";
  if (status === "PENDING") return "Order submitted. Payment is pending and will be reviewed by our team.";
  return "Order submitted successfully.";
}

function appBaseUrl(request: Request) {
  return process.env.NEXT_PUBLIC_APP_URL?.trim() || new URL(request.url).origin;
}

export async function POST(request: Request) {
  const limit = checkRateLimit(request, { route: "checkout", windowMs: 10 * 60 * 1000, maxAttempts: 10 });
  if (!limit.allowed) {
    return NextResponse.json(
      { success: false, message: "Too many requests. Please wait a few minutes and try again.", error: "Too many requests. Please wait a few minutes and try again." },
      { status: 429, headers: { "Retry-After": String(limit.retryAfterSeconds) } }
    );
  }

  let body: unknown;
  try {
    body = await request.json();
  } catch {
    return NextResponse.json({ error: "Please complete all checkout fields." }, { status: 400 });
  }
  const parsed = checkoutSchema.safeParse(body);
  if (!parsed.success) return NextResponse.json({ error: "Please complete all checkout fields." }, { status: 400 });
  const data = parsed.data;

  const items = Array.from(
    data.items.reduce((map, item) => map.set(item.productId, (map.get(item.productId) || 0) + item.quantity), new Map<string, number>()),
    ([productId, quantity]) => ({ productId, quantity })
  );
  const productIds = items.map((item) => item.productId);

  const products = await prisma.product.findMany({ where: { id: { in: productIds }, itemKind: "PHYSICAL_BULLION", isPublicProduct: true } });
  if (products.length !== productIds.length) {
    return NextResponse.json({ error: "One or more cart items are no longer available. Please review your cart." }, { status: 400 });
  }

  const enriched = items.map((item) => {
    const product = products.find((p) => p.id === item.productId);
    if (!product) throw new Error("Unavailable product");
    return { item, product };
  });

  for (const { item, product } of enriched) {
    if (product.stockStatus === "OUT_OF_STOCK" || product.inventoryStatus === "OUT_OF_STOCK") {
      return NextResponse.json({ error: `${product.name} is currently out of stock. Please remove it from your cart.` }, { status: 400 });
    }
    if (Number.isFinite(product.stockQuantity) && item.quantity > product.stockQuantity) {
      return NextResponse.json({ error: `Only ${product.stockQuantity} unit${product.stockQuantity === 1 ? "" : "s"} of ${product.name} are available. Please update your cart quantity.` }, { status: 400 });
    }
  }

  const subtotal = enriched.reduce((sum, row) => sum + displayPrice(row.product) * row.item.quantity, 0);
  const supplierTotal = enriched.reduce((sum, row) => sum + Number(row.product.supplierPrice) * row.item.quantity, 0);
  const markupTotal = subtotal - supplierTotal;
  const nextOrderNumber = orderNumber();
  const origin = appBaseUrl(request);

  let order: { id: string; orderNumber: string; paymentLogs: Array<{ id: string }> };
  try {
    order = await prisma.order.create({
      data: {
        orderNumber: nextOrderNumber,
        customerName: data.customerName,
        customerEmail: data.customerEmail,
        customerPhone: data.customerPhone,
        billingAddress: data.billingAddress,
        shippingAddress: data.shippingAddress,
        subtotal,
        supplierTotal,
        markupTotal,
        grandTotal: subtotal,
        paymentMethod: data.paymentMethod,
        paymentStatus: "PENDING",
        items: {
          create: enriched.map(({ item, product }) => ({
            productId: product.id,
            productNameSnapshot: product.name,
            supplierId: product.supplierId,
            supplierPriceSnapshot: product.supplierPrice,
            totalSalePriceSnapshot: displayPrice(product),
            quantity: item.quantity
          }))
        },
        paymentLogs: {
          create: {
            provider: data.paymentMethod,
            status: "PENDING",
            amount: subtotal,
            rawResponse: JSON.stringify({ status: "PENDING", message: "Payment attempt created." })
          }
        }
      },
      include: { paymentLogs: true }
    });
  } catch {
    return NextResponse.json({ error: "Checkout could not be started. Please review your cart and try again." }, { status: 400 });
  }

  const paymentLogId = order.paymentLogs[0]?.id;
  let payment;
  try {
    payment = await paymentProvider(data.paymentMethod).charge({
      amount: subtotal,
      currency: "USD",
      simulateFailure: data.simulateFailure,
      sourceId: data.squareSourceId,
      idempotencyKey: crypto.randomUUID(),
      referenceId: nextOrderNumber,
      returnUrl: `${origin}/api/paypal/return?orderId=${encodeURIComponent(order.id)}`,
      cancelUrl: `${origin}/api/paypal/cancel?orderId=${encodeURIComponent(order.id)}`,
      buyerEmailAddress: data.customerEmail,
      buyerPhoneNumber: data.customerPhone,
      note: `ELIT checkout ${nextOrderNumber}`
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : "Payment could not be initialized. Please try again.";
    await prisma.order.update({
      where: { id: order.id },
      data: {
        paymentStatus: "FAILED",
        paymentLogs: paymentLogId
          ? {
              update: {
                where: { id: paymentLogId },
                data: {
                  status: "FAILED",
                  rawResponse: JSON.stringify({ error: { message } })
                }
              }
            }
          : undefined
      }
    });

    return NextResponse.json({
      success: false,
      orderId: order.id,
      orderNumber: order.orderNumber,
      paymentStatus: "FAILED",
      clearCart: false,
      redirect: "/payment-failed",
      message: paymentStatusMessage("FAILED")
    });
  }

  if (payment.status === "FAILED") {
    await prisma.order.update({
      where: { id: order.id },
      data: {
        paymentStatus: "FAILED",
        paymentLogs: paymentLogId
          ? {
              update: {
                where: { id: paymentLogId },
                data: {
                  provider: payment.provider,
                  status: "FAILED",
                  rawResponse: JSON.stringify(payment.rawResponse)
                }
              }
            }
          : undefined
      }
    });

    return NextResponse.json({
      success: false,
      orderId: order.id,
      orderNumber: order.orderNumber,
      paymentStatus: "FAILED",
      clearCart: false,
      redirect: "/payment-failed",
      message: paymentStatusMessage("FAILED")
    });
  }

  if (paymentLogId) {
    await prisma.paymentLog.update({
      where: { id: paymentLogId },
      data: {
        provider: payment.provider,
        status: payment.status,
        rawResponse: JSON.stringify(payment.rawResponse)
      }
    });
  }

  if (data.paymentMethod === "PAYPAL") {
    const approvalUrl = payment.redirectUrl;

    if (typeof approvalUrl !== "string" || !approvalUrl) {
      await prisma.order.update({
        where: { id: order.id },
        data: {
          paymentStatus: "FAILED",
          paymentLogs: paymentLogId
            ? {
                update: {
                  where: { id: paymentLogId },
                  data: {
                    provider: payment.provider,
                    status: "FAILED",
                    rawResponse: JSON.stringify({ ...payment.rawResponse, error: { message: "PayPal approval link was not returned." } })
                  }
                }
              }
            : undefined
        }
      });

      return NextResponse.json({
        success: false,
        orderId: order.id,
        orderNumber: order.orderNumber,
        paymentStatus: "FAILED",
        clearCart: false,
        redirect: "/payment-failed",
        message: paymentStatusMessage("FAILED")
      });
    }

    return NextResponse.json({
      success: true,
      orderId: order.id,
      orderNumber: order.orderNumber,
      paymentStatus: "PENDING",
      clearCart: false,
      redirect: approvalUrl,
      message: "Redirecting to PayPal checkout."
    });
  }

  try {
    await prisma.$transaction(async (tx) => {
      if (payment.status === "PAID") {
        for (const { item, product } of enriched) {
          const result = await tx.product.updateMany({
            where: { id: product.id, itemKind: "PHYSICAL_BULLION", stockQuantity: { gte: item.quantity } },
            data: { stockQuantity: { decrement: item.quantity } }
          });
          if (result.count !== 1) throw new Error(`${product.name} no longer has enough stock. Please review your cart.`);
          const remainingStock = product.stockQuantity - item.quantity;
          if (remainingStock <= 0) {
            await tx.product.update({ where: { id: product.id }, data: { stockStatus: "OUT_OF_STOCK", inventoryStatus: "OUT_OF_STOCK" } });
          }
        }
      }

      return tx.order.update({
        where: { id: order.id },
        data: {
          paymentStatus: payment.status,
          paymentLogs: paymentLogId
            ? {
                update: {
                  where: { id: paymentLogId },
                  data: {
                    provider: payment.provider,
                    status: payment.status,
                    rawResponse: JSON.stringify(payment.rawResponse)
                  }
                }
              }
            : undefined
        }
      });
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : "Checkout could not be finalized. Please contact support with your order number.";
    return NextResponse.json({ error: message }, { status: 400 });
  }

  return NextResponse.json({
    success: true,
    orderId: order.id,
    orderNumber: order.orderNumber,
    paymentStatus: payment.status,
    clearCart: true,
    redirect: "/payment-success",
    message: paymentStatusMessage(payment.status)
  });
}
