// src/lib/billing/pack-fulfillment.ts — MCP credit-pack webhook fulfillment (3C).
// Called from the Stripe plugin's `onEvent` hook (src/lib/auth.ts) for EVERY
// Stripe event: only `checkout.session.completed` one-off pack purchases are
// handled, everything else is ignored. Idempotent by construction — the
// purchase row is keyed UNIQUE on stripeSessionId and the balance is only
// incremented when the insert actually happened (webhook retries are no-ops).
import "server-only";
import { randomUUID } from "node:crypto";
import { eq, sql } from "drizzle-orm";
import type Stripe from "stripe";
import { organization } from "@/lib/db/auth-schema";
import { db } from "@/lib/db/client";
import { mcpCreditPurchases } from "@/lib/db/domain-schema";

const DEFAULT_PACK_CREDITS = 25_000;
const DEFAULT_PACK_AMOUNT_CENTS = 2_500;

/** Credits the org's MCP balance for a completed pack Checkout (idempotent). */
export async function fulfillMcpPack(event: Stripe.Event): Promise<void> {
  if (event.type !== "checkout.session.completed") return;
  const session = event.data.object;
  if (session.mode !== "payment") return;
  const metadata = session.metadata;
  if (metadata?.type !== "mcp_pack") return;
  const orgId = metadata.orgId;
  if (!orgId) return;

  const credits = Number(metadata.credits) || DEFAULT_PACK_CREDITS;
  const amountCents = session.amount_total ?? DEFAULT_PACK_AMOUNT_CENTS;

  await db.transaction(async (tx) => {
    const inserted = await tx
      .insert(mcpCreditPurchases)
      .values({
        id: randomUUID(),
        orgId,
        stripeSessionId: session.id,
        credits,
        amountCents,
      })
      .onConflictDoNothing({ target: mcpCreditPurchases.stripeSessionId })
      .returning({ id: mcpCreditPurchases.id });
    // Only credit the balance when the purchase row was actually inserted —
    // a webhook retry hits the UNIQUE conflict and returns no row.
    if (inserted.length > 0) {
      await tx
        .update(organization)
        .set({
          mcpCreditBalance: sql`${organization.mcpCreditBalance} + ${credits}`,
        })
        .where(eq(organization.id, orgId));
    }
  });
}
