import { eq } from 'drizzle-orm';
import type { DrizzleClient, TxDrizzleClient } from '../../client.js';
import {
  affiliateAdminActions,
  affiliateEnrollments,
  affiliatePayouts,
  promo,
  referralLinks,
  referrals,
  referralSettings,
  users,
} from '../../schema.js';
import { asPayoutId, asReferralId } from '@/server/platform-seams/ids.js';

export type ReferralWriteDb = DrizzleClient | TxDrizzleClient;

export async function createPendingReferral(
  db: ReferralWriteDb,
  values: typeof referrals.$inferInsert,
) {
  return db
    .insert(referrals)
    .values(values)
    .onConflictDoNothing({ target: referrals.refereeUserId })
    .returning();
}

export async function updateReferralStatus(
  db: ReferralWriteDb,
  id: string,
  values: Partial<typeof referrals.$inferInsert>,
) {
  await db
    .update(referrals)
    .set(values)
    .where(eq(referrals.id, asReferralId(id)));
}

export async function updateReferralCommissionCounter(
  db: ReferralWriteDb,
  id: string,
  remaining: number,
) {
  await db
    .update(referrals)
    .set({ commissionOrdersRemaining: remaining })
    .where(eq(referrals.id, asReferralId(id)));
}

export async function updateRefereeEmailIndex(
  db: ReferralWriteDb,
  userId: string,
  emailCanonicalIndex: string,
) {
  await db.update(users).set({ emailCanonicalIndex }).where(eq(users.id, userId));
}

export async function createWelcomePromo(db: ReferralWriteDb, values: typeof promo.$inferInsert) {
  return db.insert(promo).values(values).returning();
}

export async function attachWelcomePromo(
  db: ReferralWriteDb,
  referralId: string,
  promoCodeId: string,
) {
  await db
    .update(referrals)
    .set({ refereePromoCodeId: promoCodeId })
    .where(eq(referrals.id, asReferralId(referralId)));
}

export async function createAffiliateEnrollment(
  db: ReferralWriteDb,
  values: typeof affiliateEnrollments.$inferInsert,
) {
  return db.insert(affiliateEnrollments).values(values).returning();
}

export async function createAffiliateReferralLink(
  db: ReferralWriteDb,
  values: typeof referralLinks.$inferInsert,
) {
  await db.insert(referralLinks).values(values);
}

export async function updateAffiliateEnrollment(
  db: ReferralWriteDb,
  id: string,
  values: Partial<typeof affiliateEnrollments.$inferInsert>,
) {
  return db
    .update(affiliateEnrollments)
    .set(values)
    .where(eq(affiliateEnrollments.id, asReferralId(id)))
    .returning({ id: affiliateEnrollments.id });
}

export async function recordAffiliateAdminAction(
  db: ReferralWriteDb,
  values: typeof affiliateAdminActions.$inferInsert,
) {
  await db.insert(affiliateAdminActions).values(values);
}

export async function updateReferralSettingsRow(
  db: ReferralWriteDb,
  adminUserId: string,
  patch: Partial<typeof referralSettings.$inferInsert>,
) {
  await db
    .update(referralSettings)
    .set({ ...patch, updatedAt: new Date(), updatedByUserId: adminUserId })
    .where(eq(referralSettings.id, 1));
}

export async function cancelAffiliatePayout(db: ReferralWriteDb, payoutId: string) {
  await db
    .update(affiliatePayouts)
    .set({ status: 'cancelled' })
    .where(eq(affiliatePayouts.id, asPayoutId(payoutId)));
}
