import type { Handler } from 'hono';
import { getUserCount, createUser } from 'officerdb';
import argon2 from 'argon2';
import * as errors from '@@/custom-errors';
import { rememberUser } from '@@/_middlewares';
import { validatePassword } from './validate-password';
import { validateUsername } from './validate-username';

// Single-step bootstrap for the one account Officer supports: the server owner is created directly as
// active, with no email-verification round-trip. Gated to an empty user table.
export const bootstrapHandler: Handler = async function (ctx) {
  const body = ctx.get('body');

  const userCount = await getUserCount();
  if (userCount > 0) throw errors.FORBIDDEN('Registration is closed');

  const email = body.email as string;
  const name = body.name as string;
  const username = body.username as string;
  const password = body.password as string;
  const confirmPassword = body.confirmPassword as string;

  if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    throw errors.BAD_REQUEST('Invalid email address');
  }
  if (!name || !name.trim()) throw errors.BAD_REQUEST('Name is required');
  const validUsername = validateUsername(username);
  validatePassword(password);
  if (password !== confirmPassword) throw errors.BAD_REQUEST('Passwords do not match');

  const passwordHash = await argon2.hash(password);

  // The role is what makes this account the owner — isSuperAdmin and getOwnerUser both read it, and
  // nothing else confers it. Without this the first account would take the column's 'Member' default
  // and the platform would come up with no owner at all: no vault, no agent identity, and the web
  // origin locked to a Super Admin that does not exist. Bootstrap is gated on an empty user table
  // above, so this cannot promote anyone but the first account.
  const user = await createUser({
    email,
    password: passwordHash,
    name: name.trim(),
    username: validUsername,
    status: 'Active',
    role: 'Super Admin',
  });

  // The launch-time snapshot was taken while the user table was still empty. Without this the owner's
  // very first sign-in would be filed as an unknown identity.
  rememberUser(user);

  return ctx.json({ ok: true });
};
