import type { ActionFunctionArgs } from "react-router";
import { authenticate } from "../shopify.server";
import db from "../db.server";
import {
  generateAndEmailInvoice,
  isManualPaymentOrder,
} from "../services/invoice/automations.server";
import { reserveWebhook } from "../services/webhooks/dedupe.server";
import { runWebhookInBackground } from "../services/webhooks/background.server";

/**
 * orders/create — Automation 1: when a wire-transfer (manual-payment-gateway)
 * order is placed, immediately generate and email the invoice (which includes
 * the bank details + GiroCode) so the customer can pay. Other orders are
 * ignored here; they're handled by orders/fulfilled (Automation 2).
 */
export const action = async ({ request }: ActionFunctionArgs) => {
  const { shop, topic, payload, session, admin } = await authenticate.webhook(request);
  console.log(`Received ${topic} webhook for ${shop}`);

  // Reserve this delivery (status="processing"). `null` => already
  // done/in-flight, so short-circuit. The reservation is committed only after
  // the background work succeeds, and released on failure so Shopify's retry
  // re-runs it (prevents the silent invoice loss we'd get if we recorded the
  // id as processed before the slow PDF/email work).
  const reservation = await reserveWebhook(request, shop, topic);
  if (!reservation) return new Response();

  if (!session || !admin) {
    // App uninstalled before the webhook drained — nothing to do.
    await reservation.commit();
    return new Response();
  }

  const orderId = payload?.id;
  if (orderId == null) {
    await reservation.commit();
    return new Response();
  }

  const customerLocale =
    typeof payload?.customer_locale === "string" ? payload.customer_locale : undefined;

  // Respond 200 immediately and run the (slow) PDF + email work in the
  // background — keeps us well under Shopify's ~5s ack timeout. The queue
  // commits the reservation on success and releases it on failure.
  runWebhookInBackground(
    `${topic} order=${orderId} shop=${shop}`,
    async () => {
      const settings = await db.shopSettings.findUnique({ where: { shopDomain: shop } });
      if (!settings?.autoEmailOnWireTransferPlaced) return;

      const orderGid = `gid://shopify/Order/${String(orderId).replace(/^.*\//, "")}`;
      if (!(await isManualPaymentOrder(admin, orderGid))) return;

      const result = await generateAndEmailInvoice({
        shopDomain: shop,
        admin,
        orderId,
        customerLocale,
      });
      if (!result.ok) {
        // Throw so the reservation is released and Shopify retries — don't
        // swallow the failure (which would leave the invoice unsent forever).
        throw new Error(
          `auto-email (wire-transfer placed) failed for order ${orderId} on ${shop}: ${result.reason}`,
        );
      }
    },
    reservation,
  );

  return new Response();
};
