import { builder } from "../builder";
import { ModelType, ModelListType } from "../types/index";
import { users, user_photos, files } from "../../db/schema/index";
import { eq, and, desc, asc, ilike, count, arrayContains, type SQL } from "drizzle-orm";
import type { DB } from "../../db/connection";

async function enrichModel(db: DB, user: typeof users.$inferSelect) {
  // Fetch photos
  const photoRows = await db
    .select({ id: files.id, filename: files.filename })
    .from(user_photos)
    .leftJoin(files, eq(user_photos.file_id, files.id))
    .where(eq(user_photos.user_id, user.id))
    .orderBy(user_photos.sort);

  const seen = new Set<string>();
  const photos = photoRows
    .filter((p) => p.id !== null && !seen.has(p.id!) && seen.add(p.id!))
    .map((p) => ({ id: p.id!, filename: p.filename! }));

  return { ...user, photos };
}

builder.queryField("models", (t) =>
  t.field({
    type: ModelListType,
    args: {
      featured: t.arg.boolean(),
      limit: t.arg.int(),
      search: t.arg.string(),
      offset: t.arg.int(),
      sortBy: t.arg.string(),
      tag: t.arg.string(),
    },
    resolve: async (_root, args, ctx) => {
      const pageSize = args.limit ?? 24;
      const offset = args.offset ?? 0;

      const conditions: SQL<unknown>[] = [eq(users.role, "model")];
      if (args.search) conditions.push(ilike(users.artist_name, `%${args.search}%`));
      if (args.tag) conditions.push(arrayContains(users.tags, [args.tag]));

      const order = args.sortBy === "recent" ? desc(users.date_created) : asc(users.artist_name);

      const where = and(...conditions);
      const [modelList, totalRows] = await Promise.all([
        ctx.db.select().from(users).where(where).orderBy(order).limit(pageSize).offset(offset),
        ctx.db.select({ total: count() }).from(users).where(where),
      ]);
      const items = await Promise.all(modelList.map((m) => enrichModel(ctx.db, m)));
      return { items, total: totalRows[0]?.total ?? 0 };
    },
  }),
);

builder.queryField("model", (t) =>
  t.field({
    type: ModelType,
    nullable: true,
    args: {
      slug: t.arg.string({ required: true }),
    },
    resolve: async (_root, args, ctx) => {
      const model = await ctx.db
        .select()
        .from(users)
        .where(and(eq(users.slug, args.slug), eq(users.role, "model")))
        .limit(1);

      if (!model[0]) return null;
      return enrichModel(ctx.db, model[0]);
    },
  }),
);
