import { NextRequest, NextResponse } from "next/server"; import { getWholesaleSettings, getWholesaleProducts } from "@/actions/wholesale"; import { getWholesaleCustomer } from "@/actions/wholesale-register"; import { getAdminUser } from "@/lib/admin-permissions"; import { svcHeaders } from "@/lib/svc-headers"; export const dynamic = "force-dynamic"; // POST /api/wholesale/price-sheet // Generates an HTML price sheet and enqueues it as a price_sheet notification // for one or more wholesale customers. export async function POST(req: NextRequest) { const adminUser = await getAdminUser(); if (!adminUser) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } if (!adminUser.can_manage_settings && !adminUser.can_manage_products) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } const body = await req.json(); const { customerIds, brandId, subject, customNote } = body as { customerIds: string[]; brandId: string; subject?: string; customNote?: string; }; const effectiveBrandId = adminUser.brand_id ?? brandId ?? null; if (!effectiveBrandId) { return NextResponse.json({ error: "Brand ID required" }, { status: 400 }); } if (adminUser.role === "brand_admin" && adminUser.brand_id !== brandId) { return NextResponse.json({ error: "Not authorized for this brand" }, { status: 403 }); } if (!customerIds?.length || !effectiveBrandId) { return NextResponse.json({ error: "customerIds array and brandId are required" }, { status: 400 }); } const supabaseUrl = process.env.NEXT_PUBLIC_API_URL!; const supabaseKey = process.env.POSTGREST_SERVICE_KEY!; // Fetch brand settings for branding + pickup location const settings = await getWholesaleSettings(effectiveBrandId); if (!settings) { return NextResponse.json({ error: "Brand settings not found" }, { status: 404 }); } // Fetch products for this brand const products = await getWholesaleProducts(effectiveBrandId); if (products.length === 0) { return NextResponse.json({ error: "No products found for this brand" }, { status: 404 }); } const brandName = settings.invoice_business_name ?? "Wholesale"; const pickupLocation = settings.pickup_location; const generatedDate = new Date().toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" }); const emailSubject = subject?.trim() || `${brandName} Wholesale Price Sheet — ${generatedDate}`; const hasCustomNote = Boolean(customNote?.trim()); // Build product rows HTML const productRows = products .filter(p => p.availability === "available") .map(p => { const tiersHtml = p.price_tiers .map(t => { const max = t.max_qty === 0 ? "+" : `-${t.max_qty}`; return `${t.min_qty}${max}: $${Number(t.price).toFixed(2)}`; }) .join(" | "); return ` ${p.name} ${p.description ?? "—"} ${p.unit_type} ${tiersHtml} `; }) .join(""); const html = ` ${brandName} Wholesale Price Sheet

${brandName}

Wholesale Price Sheet — ${generatedDate}

${pickupLocation ? `

Pickup: ${pickupLocation}

` : ""}
${hasCustomNote ? `

${customNote!.trim()}

` : ""}

Thank you for your wholesale account. Below is our current product availability and wholesale pricing. Prices shown are per unit. Contact us if you have questions about placing an order.

${productRows}
Product Description Unit Price Tiers

Prices subject to change. This price sheet was generated on ${generatedDate}. Contact your wholesale representative with any questions.

`; const text = `${brandName} Wholesale Price Sheet — ${generatedDate}\n${"=".repeat(50)}\n${hasCustomNote ? `\n${customNote!.trim()}\n\n` : ""}${products.filter(p => p.availability === "available").map(p => { const tiers = p.price_tiers.map(t => `${t.min_qty}${t.max_qty === 0 ? "+" : `-${t.max_qty}`}: $${Number(t.price).toFixed(2)}`).join(", "); return `${p.name} (${p.unit_type})\n ${tiers}`; }).join("\n\n")}\n\nGenerated ${generatedDate}. Prices subject to change.`; let enqueued = 0; let failed = 0; for (const customerId of customerIds) { // Fetch customer email const custRes = await fetch( `${supabaseUrl}/rest/v1/wholesale_customers?id=eq.${customerId}&select=id,email,company_name,brand_id`, { headers: { ...svcHeaders(supabaseKey) } } ); if (!custRes.ok) { failed++; continue; } const customers = await custRes.json() as Array<{ id: string; email: string; company_name: string; brand_id: string }>; const customer = customers[0]; if (!customer?.email) { failed++; continue; } const enqueueRes = await fetch( `${supabaseUrl}/rest/v1/rpc/enqueue_wholesale_notification`, { method: "POST", headers: { ...svcHeaders(supabaseKey), "Content-Type": "application/json" }, body: JSON.stringify({ p_brand_id: effectiveBrandId, p_customer_id: customerId, p_order_id: null, p_type: "price_sheet", p_email_to: customer.email, p_email_cc: settings.notification_email ?? null, p_subject: emailSubject, p_body_html: html, p_body_text: text, }), } ); if (enqueueRes.ok) { enqueued++; } else { failed++; } } // Fire-and-forget trigger to process the queue fetch(`${process.env.NEXT_PUBLIC_API_URL!}/api/wholesale/notifications/send`, { method: "POST", headers: { "Content-Type": "application/json" }, }).catch(() => {}); return NextResponse.json({ enqueued, failed, total: customerIds.length }); }