import { sql } from 'drizzle-orm';
import type { DrizzleClient } from '../client.js';
import { orderPaymentFees } from '../schema.js';

export interface UpsertOrderPaymentFeeInput {
  orderId: string;
  kind?: string;
  stripeFeeAgorot: number | null;
  providerPaymentId?: string | null;
}

/**
 * Insert or update a fee row for an order.
 *
 * ON CONFLICT semantics (idempotency + backfill):
 *   - stripe_fee_agorot: written only if currently NULL — first non-null write is sticky.
 *     Reconciler retries are no-ops once the fee is recorded; null writes (balance tx not
 *     yet ready) are overwritten on the next pass.
 *   - provider_payment_id: COALESCE — first non-null wins, never overwritten.
 *
 * Safe to call concurrently from webhook + redirect-poll + StripeReconcileDO.
 */
export async function upsertOrderPaymentFee(
  db: DrizzleClient,
  input: UpsertOrderPaymentFeeInput,
): Promise<void> {
  const { orderId, kind = 'charge', stripeFeeAgorot, providerPaymentId = null } = input;
  await db
    .insert(orderPaymentFees)
    .values({ orderId, kind, stripeFeeAgorot, providerPaymentId })
    .onConflictDoUpdate({
      target: [orderPaymentFees.orderId, orderPaymentFees.kind],
      set: {
        stripeFeeAgorot: sql`CASE WHEN ${orderPaymentFees.stripeFeeAgorot} IS NULL THEN EXCLUDED.stripe_fee_agorot ELSE ${orderPaymentFees.stripeFeeAgorot} END`,
        providerPaymentId: sql`COALESCE(${orderPaymentFees.providerPaymentId}, EXCLUDED.provider_payment_id)`,
      },
    });
}
