import { NextResponse } from "next/server"; import { ListingStatus, UserStatus } from "@prisma/client"; import { prisma } from "../../../../../lib/prisma"; import { loadN8nBillingApiKey } from "../../../../../lib/apiKeys"; import { resolveBillingDetails } from "../../../../../lib/billing"; function pickTranslation(translations: { slug: string; locale: string }[]) { return ( translations.find((t) => t.locale === "en") || translations.find((t) => t.locale === "fi") || translations[0] || null ); } function extractApiKey(req: Request) { const headerKey = req.headers.get("x-api-key"); if (headerKey) return headerKey.trim(); const auth = req.headers.get("authorization"); if (auth && auth.toLowerCase().startsWith("bearer ")) { return auth.slice(7).trim(); } return null; } export async function POST(req: Request) { const expectedKey = loadN8nBillingApiKey(); if (!expectedKey) { return NextResponse.json( { error: "Billing API key missing" }, { status: 500 }, ); } const providedKey = extractApiKey(req); if (!providedKey || providedKey !== expectedKey) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } let body: any; try { body = await req.json(); } catch { return NextResponse.json({ error: "Invalid payload" }, { status: 400 }); } const listingId = typeof body.listingId === "string" ? body.listingId : undefined; const listingSlug = typeof body.listingSlug === "string" ? body.listingSlug.trim() : undefined; const ownerEmailRaw = typeof body.ownerEmail === "string" ? body.ownerEmail.trim() : undefined; const ownerEmail = ownerEmailRaw ? ownerEmailRaw.toLowerCase() : undefined; if (!listingId && !listingSlug && !ownerEmail) { return NextResponse.json( { error: "Provide listingId, listingSlug, or ownerEmail" }, { status: 400 }, ); } let listing: any = null; if (listingId || listingSlug) { const listings = await prisma.listing.findMany({ where: { removedAt: null, status: { not: ListingStatus.REMOVED }, id: listingId ?? undefined, translations: listingSlug ? { some: { slug: listingSlug } } : undefined, }, include: { owner: { select: { id: true, email: true, status: true, approvedAt: true, emailVerifiedAt: true, billingEmailsEnabled: true, billingAccountName: true, billingIban: true, billingIncludeVatLine: true, }, }, translations: { select: { slug: true, locale: true } }, }, take: listingSlug ? 2 : 1, }); if (listingSlug && listings.length > 1) { return NextResponse.json( { error: "Listing slug is ambiguous; provide listingId" }, { status: 400 }, ); } listing = listings[0] ?? null; if (!listing && listingId) { return NextResponse.json({ error: "Listing not found" }, { status: 404 }); } if (!listing && listingSlug) { return NextResponse.json({ error: "Listing not found" }, { status: 404 }); } } let owner = listing?.owner ?? null; if (!owner && ownerEmail) { owner = await prisma.user.findFirst({ where: { email: { equals: ownerEmail, mode: "insensitive" } }, select: { id: true, email: true, status: true, approvedAt: true, emailVerifiedAt: true, billingEmailsEnabled: true, billingAccountName: true, billingIban: true, billingIncludeVatLine: true, }, }); } if (!owner) { return NextResponse.json({ enabled: false }); } const ownerReady = owner.status === UserStatus.ACTIVE && owner.approvedAt && owner.emailVerifiedAt; if (!ownerReady || !owner.billingEmailsEnabled) { return NextResponse.json({ enabled: false, owner: { id: owner.id, email: owner.email }, }); } const billing = resolveBillingDetails(owner, listing ?? undefined); const enabled = Boolean(billing.accountName && billing.iban); const listingHasOverride = listing && ((listing.billingAccountName !== null && listing.billingAccountName !== undefined) || (listing.billingIban !== null && listing.billingIban !== undefined) || (listing.billingIncludeVatLine !== null && listing.billingIncludeVatLine !== undefined)); const source = listingHasOverride ? "listing" : "user"; return NextResponse.json({ enabled, owner: { id: owner.id, email: owner.email }, listing: listing ? { id: listing.id, slug: pickTranslation(listing.translations)?.slug ?? listing.translations[0]?.slug ?? null, status: listing.status, } : null, billing: enabled ? { ...billing, source } : null, }); } export const dynamic = "force-dynamic";