/**
 * Admin image-moderation resource — read-only queries.
 *
 * - listImages: paginated list of imageUploads with optional filters.
 * - listPendingVendorHeroImages: vendor hero images awaiting approval.
 * - listVendorHeroPending: vendor hero pending OR rejected with reason code.
 */

import { eq, and, or, asc, count, isNotNull, inArray } from 'drizzle-orm';
import type { DrizzleClient } from '@/server/db/client.js';
import { imageUploads, vendors, users } from '@/server/db/schema.js';
import type { ImageRow, ListImagesOptions, VendorHeroRow, VendorHeroPendingRow } from './types.js';

// ─── listImages ───────────────────────────────────────────────────────────────

export async function listImages(
  db: DrizzleClient,
  options: ListImagesOptions,
): Promise<{ data: ImageRow[]; total: number }> {
  const { scanStatus, approvalStatus, limit, offset } = options;

  const conditions = [];
  if (scanStatus) {
    conditions.push(eq(imageUploads.scanStatus, scanStatus));
  }
  if (approvalStatus) {
    conditions.push(eq(imageUploads.approvalStatus, approvalStatus));
  }

  const whereClause = conditions.length > 0 ? and(...conditions) : undefined;

  const [rows, [countRow]] = await Promise.all([
    db
      .select({
        id: imageUploads.id,
        r2Key: imageUploads.r2Key,
        mime: imageUploads.mime,
        sizeBytes: imageUploads.sizeBytes,
        scanStatus: imageUploads.scanStatus,
        approvalStatus: imageUploads.approvalStatus,
        uploaderUserId: imageUploads.uploaderUserId,
        uploaderVendorId: imageUploads.uploaderVendorId,
        createdAt: imageUploads.createdAt,
      })
      .from(imageUploads)
      .where(whereClause)
      .orderBy(asc(imageUploads.createdAt))
      .limit(limit)
      .offset(offset),
    db.select({ count: count() }).from(imageUploads).where(whereClause),
  ]);

  const userIds = [...new Set(rows.map((r) => r.uploaderUserId).filter(Boolean) as string[])];
  const vendorIds = [...new Set(rows.map((r) => r.uploaderVendorId).filter(Boolean) as string[])];

  const userMap: Record<string, string> = {};
  const vendorMap: Record<string, string> = {};

  if (userIds.length > 0) {
    const userRows = await db
      .select({ id: users.id, displayName: users.displayName })
      .from(users)
      .where(inArray(users.id, userIds));
    for (const u of userRows) {
      if (u.displayName) userMap[u.id] = u.displayName;
    }
  }

  if (vendorIds.length > 0) {
    const vendorRows = await db
      .select({ id: vendors.id, businessName: vendors.businessName })
      .from(vendors)
      .where(inArray(vendors.id, vendorIds));
    for (const v of vendorRows) {
      vendorMap[v.id] = v.businessName;
    }
  }

  const data: ImageRow[] = rows.map((row) => ({
    ...(row as Omit<ImageRow, 'uploaderUserName' | 'uploaderVendorName'>),
    uploaderUserName: row.uploaderUserId ? (userMap[row.uploaderUserId] ?? null) : null,
    uploaderVendorName: row.uploaderVendorId ? (vendorMap[row.uploaderVendorId] ?? null) : null,
  }));

  return { data, total: countRow?.count ?? 0 };
}

// ─── listPendingVendorHeroImages ──────────────────────────────────────────────

export async function listPendingVendorHeroImages(db: DrizzleClient): Promise<VendorHeroRow[]> {
  const rows = await db
    .select({
      vendorId: vendors.id,
      displayName: vendors.displayName,
      heroImageUrl: vendors.heroImageUrl,
      heroImageR2Key: vendors.heroImageR2Key,
      heroImageApprovalStatus: vendors.heroImageApprovalStatus,
      tier: vendors.tier,
    })
    .from(vendors)
    .where(and(eq(vendors.heroImageApprovalStatus, 'PENDING'), isNotNull(vendors.heroImageUrl)));
  return rows as VendorHeroRow[];
}

// ─── listVendorHeroPending ────────────────────────────────────────────────────

export async function listVendorHeroPending(db: DrizzleClient): Promise<VendorHeroPendingRow[]> {
  return db
    .select({
      vendorId: vendors.id,
      displayName: vendors.displayName,
      heroPendingImageUrl: vendors.heroPendingImageUrl,
      heroImageApprovalStatus: vendors.heroImageApprovalStatus,
      heroImageRejectReasonCode: vendors.heroImageRejectReasonCode,
    })
    .from(vendors)
    .where(
      or(
        eq(vendors.heroImageApprovalStatus, 'PENDING'),
        and(
          eq(vendors.heroImageApprovalStatus, 'REJECTED'),
          isNotNull(vendors.heroImageRejectReasonCode),
        ),
      ),
    ) as Promise<VendorHeroPendingRow[]>;
}
