/**
 * Promo-redemption queries — append-only ledger helpers.
 */

import { and, eq, sql } from 'drizzle-orm';
import type { DrizzleClient } from '../client.js';
import { promoRedemptions, promoUserUsage } from '../schema.js';

export async function countUserRedemptions(
  db: DrizzleClient,
  userId: string,
  promoCodeId: string,
): Promise<number> {
  const [row] = await db
    .select({ uses: promoUserUsage.uses })
    .from(promoUserUsage)
    .where(and(eq(promoUserUsage.userId, userId), eq(promoUserUsage.promoId, promoCodeId)))
    .for('update')
    .limit(1);
  return row?.uses ?? 0;
}

export async function insertPromoRedemption(
  db: DrizzleClient,
  values: typeof promoRedemptions.$inferInsert,
): Promise<{ inserted: boolean }> {
  const result = await db
    .insert(promoRedemptions)
    .values(values)
    .onConflictDoNothing({ target: [promoRedemptions.orderLineId, promoRedemptions.promoCodeId] })
    .returning({ id: promoRedemptions.id });
  return { inserted: result.length === 1 };
}

/** Acquire xact-scoped advisory lock for (codeId, userId) pair. */
export async function lockUserCodeForUpdate(
  db: DrizzleClient,
  promoCodeId: string,
  userId: string,
): Promise<void> {
  await db.execute(sql`SELECT pg_advisory_xact_lock(hashtext(${promoCodeId} || ':' || ${userId}))`);
}
