import { Injectable } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import { Model, Types } from "mongoose";
import { Notification, NotificationDocument } from "./schemas/notification.schema";
import { User, UserDocument } from "./schemas/user.schema";

@Injectable()
export class NotificationsService {
  constructor(
    @InjectModel(Notification.name)
    private readonly notificationModel: Model<NotificationDocument>,
    @InjectModel(User.name)
    private readonly userModel: Model<UserDocument>,
  ) {}

  async create(payload: {
    userId: string;
    type: string;
    message: string;
    documentId?: string;
  }) {
    return this.notificationModel.create({
      userId: payload.userId,
      type: payload.type,
      message: payload.message,
      documentId: payload.documentId ?? null,
      read: false,
      createdAt: new Date().toISOString(),
    });
  }

  async notifyManagers(message: string, documentId: string) {
    const managers = await this.userModel
      .find({ role: { $in: ["store_manager", "super_admin"] }, active: true })
      .lean()
      .exec();

    await Promise.all(
      managers.map((m) =>
        this.create({
          userId: (m._id as Types.ObjectId).toString(),
          type: "approval_request",
          message,
          documentId,
        }),
      ),
    );
  }

  async notifyUser(userId: string, type: string, message: string, documentId: string) {
    return this.create({ userId, type, message, documentId });
  }

  async getForUser(userId: string) {
    const notifications = await this.notificationModel
      .find({ userId })
      .sort({ createdAt: -1 })
      .limit(50)
      .lean()
      .exec();

    return notifications.map((n) => ({
      id: (n._id as Types.ObjectId).toString(),
      type: n.type,
      message: n.message,
      documentId: n.documentId,
      read: n.read,
      createdAt: n.createdAt,
    }));
  }

  async getUnreadCount(userId: string): Promise<number> {
    return this.notificationModel.countDocuments({ userId, read: false }).exec();
  }

  async markRead(id: string, userId: string) {
    await this.notificationModel
      .findOneAndUpdate({ _id: id, userId }, { $set: { read: true } })
      .exec();
  }

  async markAllRead(userId: string) {
    await this.notificationModel
      .updateMany({ userId, read: false }, { $set: { read: true } })
      .exec();
  }
}
