/**
 * First-run bootstrap: lets the very first operator self-register as the
 * super-admin on a fresh DB. Safe because the only "do it" path
 * (`createInitialSuperAdmin`) refuses to run when any super-admin row
 * already exists, so the window closes the moment the first account is
 * created.
 */

import { eq } from 'drizzle-orm';

import { db } from '@/lib/db';
import { user, userProfiles } from '@/lib/db/schema';
import { auth } from '@/lib/auth';
import { ConflictError, ValidationError } from '@/lib/errors';

/** True when no user has `is_super_admin = true` in user_profiles. */
export async function hasAnySuperAdmin(): Promise<boolean> {
  const row = await db
    .select({ userId: userProfiles.userId })
    .from(userProfiles)
    .where(eq(userProfiles.isSuperAdmin, true))
    .limit(1);
  return row.length > 0;
}

export interface BootstrapInput {
  name: string;
  email: string;
  password: string;
}

/**
 * Atomically: create the better-auth user, create the user_profiles row
 * with isSuperAdmin=true. Refuses to run when a super-admin already
 * exists - the only safe-by-design self-registration path.
 *
 * Returns the new user's id on success.
 */
export async function createInitialSuperAdmin(input: BootstrapInput): Promise<string> {
  if (input.password.length < 9) {
    throw new ValidationError('Password must be at least 9 characters');
  }
  if (!input.email.includes('@')) {
    throw new ValidationError('A valid email is required');
  }
  if (!input.name.trim()) {
    throw new ValidationError('Name is required');
  }

  // Re-check inside the critical path so two concurrent first-run
  // submissions can't both win - the first to insert the profile row
  // closes the window for everyone else.
  if (await hasAnySuperAdmin()) {
    throw new ConflictError('A super-administrator account already exists');
  }

  const email = input.email.toLowerCase().trim();
  const existing = await db.query.user.findFirst({ where: eq(user.email, email) });
  if (existing) {
    // Either someone signed up via a different flow first, or we're
    // racing a portal-activation. Refuse rather than silently re-purpose.
    throw new ConflictError('A user with this email already exists');
  }

  const authResult = await auth.api.signUpEmail({
    body: {
      email,
      password: input.password,
      name: input.name.trim(),
    },
  });

  const newUserId = authResult.user.id;

  await db.insert(userProfiles).values({
    userId: newUserId,
    displayName: input.name.trim(),
    isSuperAdmin: true,
  });

  return newUserId;
}
