import {
  buildPaginatedResult,
  DEFAULT_PAGE_SIZE,
  ok,
  type PaginationInput,
  type QueryContext,
  type ReadonlyDB,
} from "@tailor-platform/erp-kit/core";
import type { DB } from "../generated/kysely-tailordb";

export interface ListInboxNotificationsInput extends PaginationInput<never> {
  includeArchived?: boolean;
}

/**
 * Returns the caller's paginated IN_APP inbox feed (SENT/DELIVERED, archived excluded by default) plus the unread count over the caller's deliverable, unread, non-archived set.
 */
export async function run(
  db: ReadonlyDB<DB>,
  input: ListInboxNotificationsInput,
  ctx: QueryContext,
) {
  const limit = input.limit ?? DEFAULT_PAGE_SIZE;
  const offset = input.offset ?? 0;
  const includeArchived = input.includeArchived === true;

  // The inbox is the IN_APP surface only; rows dispatched on other channels
  // (e.g. EMAIL) are delivered by their adapter and must not appear in the feed.
  let feedQuery = db
    .selectFrom("Notification")
    .innerJoin("NotificationChannel", "NotificationChannel.id", "Notification.channelId")
    .where("NotificationChannel.channelId", "=", "IN_APP")
    .selectAll("Notification")
    .where("recipientUserId", "=", ctx.actorId)
    .where("deliveryStatus", "in", ["SENT", "DELIVERED"]);

  if (!includeArchived) {
    feedQuery = feedQuery.where("archivedAt", "is", null);
  }

  const page = await feedQuery
    .orderBy("createdAt", "desc")
    .limit(limit + 1)
    .offset(offset)
    .execute();

  const unread = await db
    .selectFrom("Notification")
    .innerJoin("NotificationChannel", "NotificationChannel.id", "Notification.channelId")
    .where("NotificationChannel.channelId", "=", "IN_APP")
    .where("recipientUserId", "=", ctx.actorId)
    .where("deliveryStatus", "in", ["SENT", "DELIVERED"])
    .where("readAt", "is", null)
    .where("archivedAt", "is", null)
    .select((eb) => eb.fn.countAll<number>().as("count"))
    .executeTakeFirst();

  const unreadCount = Number(unread?.count ?? 0);

  return ok({ ...buildPaginatedResult(page, limit), unreadCount });
}
