/**
 * Admin users resource — write actions.
 *
 * - freezeUser: set accountState to FROZEN, write audit log.
 * - unfreezeUser: set accountState to ACTIVE, write audit log.
 * - setAdminFlag: grant/revoke admin role, write audit log.
 *
 * All admin actions write to admin_actions audit table.
 */

import type { DrizzleClient } from '@/server/db/client.js';
import { UserManagementError } from './errors.js';
import type { FreezeUserInput, UnfreezeUserInput, SetAdminFlagInput } from './types.js';
import { bumpMhVersion } from '@/server/auth/session.js';
import { recordAdminAction } from '@/server/db/queries/admin-actions.js';
import { findById, setUserAccountState, setUserAdminFlag } from '@/server/db/queries/users.js';

// ─── freezeUser ───────────────────────────────────────────────────────────────

export async function freezeUser(db: DrizzleClient, input: FreezeUserInput): Promise<void> {
  const { adminId, userId, reason } = input;

  const user = await findById(db, userId);

  if (!user) {
    throw new UserManagementError('USER_NOT_FOUND', 'User not found');
  }
  if (user.accountState === 'FROZEN') {
    throw new UserManagementError('INVALID_STATE', 'User is already frozen');
  }
  if (user.accountState === 'DELETED' || user.accountState === 'DELETED_PENDING') {
    throw new UserManagementError('INVALID_STATE', 'Cannot freeze a deleted user');
  }

  await setUserAccountState(db, userId, 'FROZEN');
  await bumpMhVersion(db, userId);

  await recordAdminAction(db, {
    adminId,
    targetType: 'USER',
    targetId: userId,
    action: 'FREEZE',
    note: reason,
  });
}

// ─── unfreezeUser ─────────────────────────────────────────────────────────────

export async function unfreezeUser(db: DrizzleClient, input: UnfreezeUserInput): Promise<void> {
  const { adminId, userId, note } = input;

  const user = await findById(db, userId);

  if (!user) {
    throw new UserManagementError('USER_NOT_FOUND', 'User not found');
  }
  if (user.accountState !== 'FROZEN') {
    throw new UserManagementError('INVALID_STATE', 'User is not frozen');
  }

  await setUserAccountState(db, userId, 'ACTIVE');
  await bumpMhVersion(db, userId);

  await recordAdminAction(db, {
    adminId,
    targetType: 'USER',
    targetId: userId,
    action: 'UNFREEZE',
    note: note ?? null,
  });
}

// ─── setAdminFlag ─────────────────────────────────────────────────────────────

export async function setAdminFlag(db: DrizzleClient, input: SetAdminFlagInput): Promise<void> {
  const { adminId, userId, isAdmin, reason } = input;

  const user = await findById(db, userId);

  if (!user) {
    throw new UserManagementError('USER_NOT_FOUND', 'User not found');
  }
  if (user.isAdmin === isAdmin) {
    throw new UserManagementError(
      'INVALID_STATE',
      isAdmin ? 'User is already an admin' : 'User is not an admin',
    );
  }

  await setUserAdminFlag(db, userId, isAdmin);
  await bumpMhVersion(db, userId);

  await recordAdminAction(db, {
    adminId,
    targetType: 'USER',
    targetId: userId,
    action: isAdmin ? 'GRANT_ADMIN' : 'REVOKE_ADMIN',
    note: reason ?? null,
  });
}
