import { NextRequest, NextResponse } from "next/server";
import { processReceiptIngestion, ReceiptValidationError, validateReceipt, type ParsedReceipt } from "@/lib/receipt-ingestion";

/**
 * Machine ingest endpoint for grocery receipts scanned in pantry-app.
 *
 * Sibling to /api/orders/ingest and deliberately shaped like it. Auth is a shared secret
 * rather than the Traefik `x-forwarded-user` header: this is called app-to-app, and there
 * is no browser session to forward.
 *
 * Its own token rather than ORDER_INGEST_TOKEN so pantry's credential can be rotated
 * without touching the n8n order flow, which runs on a schedule nobody is watching.
 */
function authorised(req: NextRequest): boolean {
  const expected = process.env.RECEIPT_INGEST_TOKEN;
  if (!expected) return false; // fail closed when unconfigured
  const got = req.headers.get("x-ingest-token");
  return !!got && got === expected;
}

export async function POST(req: NextRequest) {
  if (!authorised(req)) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  let body: ParsedReceipt & { dryRun?: boolean };
  try {
    body = await req.json();
  } catch {
    return NextResponse.json({ error: "invalid JSON" }, { status: 400 });
  }

  if (!body?.merchant_name || !body?.transaction_date || typeof body?.total !== "number" || !Number.isInteger(body?.capture_event_id)) {
    return NextResponse.json({ error: "merchant_name, transaction_date, total and capture_event_id are required" }, { status: 400 });
  }

  try {
    // Dry run validates and reports what would be written without writing it — the same
    // affordance every maintenance script in pantry has, and for the same reason: the first
    // pass over a new receipt format is worth reading before it becomes money.
    if (body.dryRun) return NextResponse.json({ kind: "receipt", dryRun: true, flags: validateReceipt(body) });
    const result = await processReceiptIngestion(body);
    return NextResponse.json({ kind: "receipt", ...result });
  } catch (e) {
    // A receipt that will not validate is the failure that matters: it means the payment
    // side was read wrong, and booking it anyway would put a number in the ledger nobody
    // can stand behind. Loud, like OrderParseError.
    if (e instanceof ReceiptValidationError) {
      return NextResponse.json({ kind: "rejected", reason: e.message }, { status: 422 });
    }
    const message = e instanceof Error ? e.message : String(e);
    return NextResponse.json({ error: message }, { status: 500 });
  }
}
