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

export async function findEnqueuedReleases(db: DrizzleClient, ids: string[]) {
  return db
    .select()
    .from(vendorPayoutReleases)
    .where(and(inArray(vendorPayoutReleases.id, ids), eq(vendorPayoutReleases.status, 'enqueued')));
}

export async function findReleasingReleases(db: DrizzleClient, ids: string[]) {
  return db
    .select()
    .from(vendorPayoutReleases)
    .where(
      and(inArray(vendorPayoutReleases.id, ids), eq(vendorPayoutReleases.status, 'releasing')),
    );
}

export async function claimReleases(db: DrizzleClient, ids: string[]) {
  return db
    .update(vendorPayoutReleases)
    .set({ status: 'releasing', claimedAt: new Date(), claimAttempts: sql`claim_attempts + 1` })
    .where(and(inArray(vendorPayoutReleases.id, ids), eq(vendorPayoutReleases.status, 'enqueued')))
    .returning({
      id: vendorPayoutReleases.id,
      payoutIdempotencyKey: vendorPayoutReleases.payoutIdempotencyKey,
      payoutIdempotencyKeyCreatedAt: vendorPayoutReleases.payoutIdempotencyKeyCreatedAt,
    });
}

export async function persistPayoutIdempotencyKey(
  db: DrizzleClient,
  ids: string[],
  payoutIdempotencyKey: string,
) {
  return db
    .update(vendorPayoutReleases)
    .set({ payoutIdempotencyKey, payoutIdempotencyKeyCreatedAt: sql`now()` })
    .where(
      and(
        inArray(vendorPayoutReleases.id, ids),
        eq(vendorPayoutReleases.status, 'releasing'),
        isNull(vendorPayoutReleases.payoutIdempotencyKey),
      ),
    )
    .returning({
      id: vendorPayoutReleases.id,
      payoutIdempotencyKey: vendorPayoutReleases.payoutIdempotencyKey,
      payoutIdempotencyKeyCreatedAt: vendorPayoutReleases.payoutIdempotencyKeyCreatedAt,
    });
}

export async function holdReleases(db: DrizzleClient, ids: string[], lastError: string) {
  return db
    .update(vendorPayoutReleases)
    .set({ status: 'held', lastError })
    .where(and(inArray(vendorPayoutReleases.id, ids), eq(vendorPayoutReleases.status, 'releasing')))
    .returning({ id: vendorPayoutReleases.id });
}

export async function settleReleases(
  db: DrizzleClient,
  ids: string[],
  status: 'held' | 'enqueued',
  lastError: string,
) {
  return db
    .update(vendorPayoutReleases)
    .set({ status, lastError })
    .where(and(inArray(vendorPayoutReleases.id, ids), eq(vendorPayoutReleases.status, 'releasing')))
    .returning({ id: vendorPayoutReleases.id });
}

export async function releaseReleases(db: DrizzleClient, ids: string[], payoutId: string) {
  return db
    .update(vendorPayoutReleases)
    .set({ status: 'released', releasedAt: new Date(), payoutId, lastError: null })
    .where(and(inArray(vendorPayoutReleases.id, ids), eq(vendorPayoutReleases.status, 'releasing')))
    .returning({ id: vendorPayoutReleases.id });
}
