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

export type ToggleResult = { saved: boolean; notify: boolean };

export async function toggleFavoriteVendor(
  db: DrizzleClient,
  userId: string,
  vendorId: string,
  notify = false,
): Promise<ToggleResult> {
  const [existing] = await db
    .select({ id: favoriteVendors.id, notify: favoriteVendors.notify })
    .from(favoriteVendors)
    .where(and(eq(favoriteVendors.userId, userId), eq(favoriteVendors.vendorId, vendorId)));

  if (existing) {
    await db.delete(favoriteVendors).where(eq(favoriteVendors.id, existing.id));
    return { saved: false, notify: false };
  }

  const [inserted] = await db
    .insert(favoriteVendors)
    .values({ userId, vendorId, notify })
    .returning({ id: favoriteVendors.id, notify: favoriteVendors.notify });

  return { saved: true, notify: inserted?.notify ?? notify };
}

export type FavoriteVendorRow = {
  id: string;
  vendorId: string;
  notify: boolean;
  createdAt: Date;
  vendor: {
    id: string;
    displayName: string;
    logoUrl: string | null;
    businessTypeNames: string[];
  };
};

export async function getFavoriteVendors(
  db: DrizzleClient,
  userId: string,
): Promise<FavoriteVendorRow[]> {
  return db
    .select({
      id: favoriteVendors.id,
      vendorId: favoriteVendors.vendorId,
      notify: favoriteVendors.notify,
      createdAt: favoriteVendors.createdAt,
      vendor: {
        id: vendors.id,
        displayName: vendors.displayName,
        logoUrl: vendors.logoUrl,
        businessTypeNames: sql<string[]>`COALESCE(
          (SELECT array_agg(bt.name_he ORDER BY bt.sort_order)
             FROM vendor_business_types vbt
             JOIN business_types bt ON bt.id = vbt.business_type_id
            WHERE vbt.vendor_id = ${vendors.id}),
          ARRAY[]::text[]
        )`,
      },
    })
    .from(favoriteVendors)
    .innerJoin(vendors, eq(favoriteVendors.vendorId, vendors.id))
    .where(eq(favoriteVendors.userId, userId))
    .orderBy(favoriteVendors.createdAt);
}

export async function getFavoritedVendorIds(db: DrizzleClient, userId: string): Promise<string[]> {
  const rows = await db
    .select({ vendorId: favoriteVendors.vendorId })
    .from(favoriteVendors)
    .where(eq(favoriteVendors.userId, userId));
  return rows.map((r) => r.vendorId);
}

export async function setFavoriteVendorNotify(
  db: DrizzleClient,
  userId: string,
  vendorId: string,
  notify: boolean,
): Promise<void> {
  await db
    .update(favoriteVendors)
    .set({ notify })
    .where(and(eq(favoriteVendors.userId, userId), eq(favoriteVendors.vendorId, vendorId)));
}

export async function setFavoriteVendorNotifyAll(
  db: DrizzleClient,
  userId: string,
  notify: boolean,
): Promise<void> {
  await db.update(favoriteVendors).set({ notify }).where(eq(favoriteVendors.userId, userId));
}

export async function getUsersToNotifyForVendor(
  db: DrizzleClient,
  vendorId: string,
): Promise<string[]> {
  const rows = await db
    .select({ userId: favoriteVendors.userId })
    .from(favoriteVendors)
    .where(and(eq(favoriteVendors.vendorId, vendorId), eq(favoriteVendors.notify, true)));
  return rows.map((r) => r.userId);
}
