import { NextResponse } from "next/server";
import type { CartItem } from "../../lib/cart";
import { getShippingMethods, getPaymentMethods, getCompanySettings } from "../../lib/payload";
import { validateDiscountCode, redeemDiscountCode } from "../../lib/discountServer";
import { createOrder } from "../../lib/orderServer";
import { getSessionCustomer, registerCustomer, setSessionCookie, type CustomerSummary } from "../../lib/customerAuth";
import { fetchProductsBySlug } from "../../lib/productsServer";
import { describeBundleContents } from "../../lib/bundleContents";
import { sendCriticalAlert } from "../../lib/alertAdmin";
import { sendOrderConfirmationEmail } from "../../lib/orderEmail";

type CheckoutBody = {
  cart: CartItem[];
  shippingMethodId: number;
  paymentMethodId: number;
  discountCode: string | null;
  firstName: string;
  lastName: string;
  email: string;
  password?: string;
  deliveryMethod: "address" | "packstation";
  street?: string;
  packstationNumber?: string;
  postNumber?: string;
  zip: string;
  city: string;
  country: string;
  newsletterOptIn: boolean;
};

function isValidBody(body: unknown): body is CheckoutBody {
  const b = body as Partial<CheckoutBody> | null;
  return Boolean(
    b &&
      Array.isArray(b.cart) &&
      b.cart.length > 0 &&
      typeof b.shippingMethodId === "number" &&
      typeof b.paymentMethodId === "number" &&
      typeof b.firstName === "string" &&
      b.firstName &&
      typeof b.lastName === "string" &&
      b.lastName &&
      typeof b.email === "string" &&
      b.email &&
      (b.deliveryMethod === "address" || b.deliveryMethod === "packstation") &&
      typeof b.zip === "string" &&
      b.zip &&
      typeof b.city === "string" &&
      b.city &&
      typeof b.country === "string" &&
      b.country,
  );
}

export async function POST(request: Request) {
  const body = await request.json().catch(() => null);
  if (!isValidBody(body)) {
    return NextResponse.json({ ok: false, reason: "Bitte alle Pflichtfelder ausfüllen." }, { status: 400 });
  }
  if (body.deliveryMethod === "address" && !body.street) {
    return NextResponse.json({ ok: false, reason: "Bitte Straße und Hausnummer angeben." }, { status: 400 });
  }
  if (body.deliveryMethod === "packstation" && (!body.packstationNumber || !body.postNumber)) {
    return NextResponse.json({ ok: false, reason: "Bitte Packstation- und Postnummer angeben." }, { status: 400 });
  }

  // Auth: an existing session wins; otherwise this checkout submit doubles
  // as inline registration ("Konto Pflicht, Registrierung direkt im
  // Checkout") — logging in with an *existing* account happens separately
  // beforehand via /api/account/login from the checkout page's own toggle.
  let customer: CustomerSummary;
  const session = await getSessionCustomer();
  if (session) {
    customer = session.customer;
  } else {
    if (!body.password) {
      return NextResponse.json({ ok: false, reason: "Bitte ein Passwort für dein neues Konto vergeben." }, { status: 400 });
    }
    const result = await registerCustomer({
      firstName: body.firstName,
      lastName: body.lastName,
      email: body.email,
      password: body.password,
    });
    if (!result.ok) return NextResponse.json(result, { status: 400 });
    await setSessionCookie(result.token);
    customer = result.customer;
  }

  // Re-price everything server-side — never trust client-submitted prices.
  const [productsBySlug, companySettings] = await Promise.all([fetchProductsBySlug(), getCompanySettings()]);
  const defaultTaxRate = companySettings?.taxRatePercent ?? 19;
  const items: {
    productId: number;
    productName: string;
    quantity: number;
    unitPrice: number;
    imageUrl: string | null;
    taxRatePercent: number;
    bundleContents: string | null;
  }[] = [];
  for (const line of body.cart) {
    const product = productsBySlug.get(line.id);
    if (!product) return NextResponse.json({ ok: false, reason: "Ein Artikel im Warenkorb ist nicht mehr verfügbar." }, { status: 400 });
    const imageUrl = typeof product.image === "object" && product.image ? product.image.url : null;
    items.push({
      productId: product.id,
      productName: product.name,
      quantity: line.qty,
      unitPrice: product.price,
      imageUrl,
      taxRatePercent: product.taxRatePercent ?? defaultTaxRate,
      bundleContents: describeBundleContents(product),
    });
  }
  const subtotal = items.reduce((sum, i) => sum + i.quantity * i.unitPrice, 0);

  const shippingMethods = await getShippingMethods();
  const shippingMethod = shippingMethods.find((m) => m.id === body.shippingMethodId);
  if (!shippingMethod) return NextResponse.json({ ok: false, reason: "Versandart ist ungültig." }, { status: 400 });
  const freeShipping = shippingMethod.freeShippingThreshold != null && subtotal >= shippingMethod.freeShippingThreshold;
  const shippingCost = freeShipping ? 0 : shippingMethod.price;

  const paymentMethods = await getPaymentMethods();
  const paymentMethod = paymentMethods.find((m) => m.id === body.paymentMethodId);
  if (!paymentMethod) return NextResponse.json({ ok: false, reason: "Zahlungsart ist ungültig." }, { status: 400 });

  let discountAmount = 0;
  if (body.discountCode) {
    const validation = await validateDiscountCode(body.discountCode, subtotal);
    if (!validation.valid) return NextResponse.json({ ok: false, reason: validation.reason }, { status: 400 });
    const redeemed = await redeemDiscountCode(validation.doc);
    if (!redeemed) return NextResponse.json({ ok: false, reason: "Rabattcode konnte nicht eingelöst werden." }, { status: 400 });
    discountAmount =
      validation.doc.type === "percent" ? (subtotal * validation.doc.value) / 100 : Math.min(validation.doc.value, subtotal);
  }
  const total = Math.max(0, subtotal - discountAmount) + shippingCost;

  const order = await createOrder({
    customerId: customer.id,
    customerFirstName: body.firstName,
    customerLastName: body.lastName,
    customerEmail: body.email,
    deliveryMethod: body.deliveryMethod,
    street: body.street,
    packstationNumber: body.packstationNumber,
    postNumber: body.postNumber,
    zip: body.zip,
    city: body.city,
    country: body.country,
    newsletterOptIn: Boolean(body.newsletterOptIn),
    items,
    subtotal,
    shippingCost,
    shippingMethodTitle: shippingMethod.title,
    paymentMethodTitle: paymentMethod.title,
    discountCode: body.discountCode || null,
    discountAmount,
    total,
  });
  if (!order) {
    // The worst-case failure in this whole flow: the customer went
    // through checkout believing they bought something, and nothing was
    // persisted. Kuma's uptime checks can't see this (the site is up,
    // this route just returned a 500) — this is the one alert path that
    // can.
    sendCriticalAlert("Bestellung konnte nicht gespeichert werden", {
      customerId: customer.id,
      customerEmail: body.email,
      cart: body.cart,
      total,
      timestamp: new Date().toISOString(),
    });
    return NextResponse.json({ ok: false, reason: "Bestellung konnte nicht gespeichert werden." }, { status: 500 });
  }

  // Fire-and-forget — a failed confirmation email must never undo an
  // already-successful order or block the response the customer is
  // waiting on. Lower severity than the "order lost" alert above (the
  // order itself is safe either way), but still worth knowing about, since
  // it's the one thing that would otherwise fail completely silently.
  sendOrderConfirmationEmail(
    {
      orderNumber: order.orderNumber,
      createdAt: order.createdAt,
      invoiceNumber: order.invoiceNumber,
      invoiceIssuedAt: order.invoiceIssuedAt,
      customerFirstName: body.firstName,
      customerLastName: body.lastName,
      deliveryMethod: body.deliveryMethod,
      street: body.street,
      packstationNumber: body.packstationNumber,
      postNumber: body.postNumber,
      zip: body.zip,
      city: body.city,
      country: body.country,
      paymentMethodTitle: paymentMethod.title,
      items: items.map((i) => ({
        productName: i.productName,
        quantity: i.quantity,
        unitPrice: i.unitPrice,
        imageUrl: i.imageUrl,
        taxRatePercent: i.taxRatePercent,
        bundleContents: i.bundleContents,
      })),
      subtotal,
      shippingCost,
      discountAmount,
      discountCode: body.discountCode || null,
      total,
    },
    body.email,
  ).catch((err) => {
    sendCriticalAlert("Bestätigungs-Mail konnte nicht gesendet werden", {
      orderNumber: order.orderNumber,
      customerEmail: body.email,
      error: String(err),
    });
  });

  return NextResponse.json({
    ok: true,
    orderNumber: order.orderNumber,
    orderDateIso: order.createdAt,
    shippingCost,
    paymentMethodTitle: paymentMethod.title,
    discountCode: body.discountCode || null,
    discountAmount,
  });
}
