import { BaseRepository } from "@edr/api-common";
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { FindOptionsWhere, Repository } from "typeorm";

import { Notification } from "./entities/notification.entity";

@Injectable()
export class NotificationInboxRepository extends BaseRepository<Notification> {
  constructor(
    @InjectRepository(Notification)
    repo: Repository<Notification>,
  ) {
    super(repo);
  }

  /** Newest-first page of a recipient's notifications, optionally read-filtered. */
  async findForRecipient(
    userId: string,
    opts: { page?: number; limit?: number; isRead?: boolean } = {},
  ): Promise<[Notification[], number]> {
    const page = opts.page && opts.page > 0 ? opts.page : 1;
    const limit = opts.limit && opts.limit > 0 ? opts.limit : 20;
    const where: FindOptionsWhere<Notification> = { recipientUserId: userId };
    if (typeof opts.isRead === "boolean") {
      where.isRead = opts.isRead;
    }
    return this.repository.findAndCount({
      where,
      order: { createdAt: "DESC" },
      skip: (page - 1) * limit,
      take: limit,
    });
  }

  async countUnread(userId: string): Promise<number> {
    return this.repository.count({
      where: { recipientUserId: userId, isRead: false },
    });
  }

  /** Mark a single notification read (scoped to its recipient). Returns true if it changed. */
  async markRead(id: string, userId: string): Promise<boolean> {
    const result = await this.repository.update(
      { id, recipientUserId: userId, isRead: false },
      { isRead: true, readAt: new Date() },
    );
    return (result.affected ?? 0) > 0;
  }

  /** Mark all of a recipient's unread notifications read. Returns the count updated. */
  async markAllRead(userId: string): Promise<number> {
    const result = await this.repository.update(
      { recipientUserId: userId, isRead: false },
      { isRead: true, readAt: new Date() },
    );
    return result.affected ?? 0;
  }
}
