import { db } from "@/db/client";
import { users, userIdentities } from "@/db/schema";
import { eq, and } from "drizzle-orm";

// Finds or creates a local user record for an authenticated OIDC identity.
// Returns the local user id.
export async function findOrCreateUser({
  externalId,
  provider,
  name,
  email,
  isAdmin,
}: {
  externalId: string;
  provider: string;
  name: string;
  email: string;
  isAdmin: boolean;
}): Promise<string> {
  const existingIdentity = await db
    .select({ userId: userIdentities.userId })
    .from(userIdentities)
    .where(
      and(
        eq(userIdentities.provider, provider),
        eq(userIdentities.externalId, externalId)
      )
    )
    .limit(1);

  if (existingIdentity.length > 0) {
    await db
      .update(users)
      .set({ displayName: name, email, isAdmin, updatedAt: new Date() })
      .where(eq(users.id, existingIdentity[0].userId));
    return existingIdentity[0].userId;
  }

  const existingUser = email
    ? await db
        .select({ id: users.id })
        .from(users)
        .where(eq(users.email, email))
        .limit(1)
    : [];

  if (existingUser.length > 0) {
    await db
      .update(users)
      .set({ displayName: name, isAdmin, updatedAt: new Date() })
      .where(eq(users.id, existingUser[0].id));

    await db.insert(userIdentities).values({
      userId: existingUser[0].id,
      provider,
      externalId,
    });

    return existingUser[0].id;
  }

  const [newUser] = await db
    .insert(users)
    .values({ displayName: name, email, isAdmin })
    .returning({ id: users.id });

  await db.insert(userIdentities).values({
    userId: newUser.id,
    provider,
    externalId,
  });

  return newUser.id;
}
