import type { UserAdminEngine } from '@platform-modules/auth';
import {
  createDbNotificationStore,
  type NotificationsSchema,
} from '@platform-modules/notifications/inbox';
import type { Querier } from '@platform-modules/db';
import { getFullDb, type DbEnv } from './db.js';

export type AdminNotificationEvent = 'submission.created' | 'comment.created';

export const SUBMISSION_CREATED_EVENT: AdminNotificationEvent = 'submission.created';
export const COMMENT_CREATED_EVENT: AdminNotificationEvent = 'comment.created';

const EVENT_PAYLOADS: Record<
  AdminNotificationEvent,
  { title: string; href: string; kind: string }
> = {
  'submission.created': {
    title: 'New contact submission',
    href: '/admin/submissions',
    kind: 'submission',
  },
  'comment.created': {
    title: 'New comment pending moderation',
    href: '/admin/comments',
    kind: 'comment',
  },
};

/** Notifications db handle — reuses the host full-db client typed to NotificationsSchema. */
export function getNotificationsDb(env: DbEnv): Querier<NotificationsSchema> {
  return getFullDb(env).db as unknown as Querier<NotificationsSchema>;
}

/** Recipients = active admins (users who pass the linked route's requireAdmin gate today). */
export async function resolveAdminRecipientIds(engine: UserAdminEngine): Promise<string[]> {
  const ids: string[] = [];
  let offset = 0;
  while (true) {
    const page = await engine.listUsers({ limit: 500, offset });
    for (const user of page.users) {
      if (user.status === 'active' && user.roles.includes('admin')) {
        ids.push(user.id);
      }
    }
    offset += page.users.length;
    if (offset >= page.total || page.users.length === 0) break;
  }
  return ids;
}

/** Best-effort fan-out — never throws; one failed put must not abort others. */
export async function notifyAdmins(
  env: DbEnv,
  engine: UserAdminEngine,
  event: AdminNotificationEvent,
): Promise<void> {
  try {
    const recipients = await resolveAdminRecipientIds(engine);
    if (recipients.length === 0) return;

    const payload = EVENT_PAYLOADS[event];
    const store = createDbNotificationStore(getNotificationsDb(env));
    await Promise.allSettled(
      recipients.map((userId) =>
        store.put({
          userId,
          title: payload.title,
          href: payload.href,
          kind: payload.kind,
        }),
      ),
    );
  } catch {
    // Swallow recipient-resolution and unexpected errors — notification failure is not a source-event failure.
  }
}
