import { Injectable } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import { Model } from "mongoose";
import { FirebaseProvider } from "src/common/firebase/firebase.provider";
import { UserDevicesService } from "src/user-devices/user-devices.service";
import { AlertType } from "./alert.types";
import { Notification } from "src/schema/notificatiom.schema";
import { ResponseService } from "src/common/service/response.service";
import { Users } from "src/schema/users.schema";
import { Response } from "express";

@Injectable()
export class AlertsService {
  constructor(
    private readonly firebase: FirebaseProvider,
    private readonly devicesService: UserDevicesService,
    private readonly resService: ResponseService,

    @InjectModel(Notification.name)
    private readonly notificationModel: Model<Notification>,

    @InjectModel(Users.name)
    private readonly userModel: Model<Users>,
  ) {}

  /**
   * MAIN ENTRY POINT
   */
  async sendAlert(
    userId: string,
    type: AlertType,
    title: string,
    message: string,
    data: Record<string, any>,
  ) {
    try {
        await this.userModel.findByIdAndUpdate(userId, {
      hasUnreadNotification: true,
    });
      const notification = await this.notificationModel.create({
        userId,
        type,
        title,
        message,
        data,
      });
      // 2️⃣ Check global notification toggle
      const user = await this.userModel
        .findById(userId)
        .select("notificationsEnabled")
        .lean();

      if (!user?.notificationsEnabled) {
        return notification;
      }

      // 3️⃣ Send push via Firebase
      const tokens = await this.devicesService.getTokens(userId);
      if (tokens.length > 0) {
        await this.firebase.send(tokens, title, message, {
          notificationId: notification._id.toString(),
          type,
        });
      }
     return ;
    } catch (error) {
      console.error("Error in sendAlert:", error);
      throw error;
    }
  }

async getUserNotifications(
  res:Response,
  userId: string,
  page: number = 1,
  limit: number = 10,
) {
  try {
    // Prevent invalid values
    page = page < 1 ? 1 : page;
    limit = limit > 50 ? 50 : limit;

    const skip = (page - 1) * limit;

    const [notifications, totalCount , user] = await Promise.all([
      this.notificationModel
        .find({ userId })
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(limit)
        .lean(),

      this.notificationModel.countDocuments({ userId }),


      this.userModel
        .findById(userId)
        .select("hasUnreadNotification")
        .lean<{ hasUnreadNotification?: boolean }>(),
    ]);
       const hasUnreadNotification = user?.hasUnreadNotification || false;

    // Reset unread flag after fetching notifications
    await this.userModel.findByIdAndUpdate(userId, {
      hasUnreadNotification: false,
    });

    const totalPages = Math.ceil(totalCount / limit);

    return this.resService.success(res , { 
      page,
      limit,
      totalPages,
      totalCount,
       hasUnreadNotification,
      data: notifications,
    }, "Sucessfully fetch notifications" ) 
  } catch (error) {
    console.error('Error fetching notifications:', error);
    return this.resService.serverError(res , "")
  }
}


  // ---------- Convenience wrappers ----------

  invoiceSent(userId: string, invoice: any) {
    return this.sendAlert(
      userId,
      AlertType.INVOICE_SENT,
      "Invoice sent",
      `Invoice #${invoice.number} has been sent`,
      { invoiceId: invoice._id },
    );
  }

  estimateSent(userId: string, estimate: any) {
    return this.sendAlert(
      userId,
      AlertType.ESTIMATE_SENT,
      "Estimate sent",
      `Estimate #${estimate.number} has been sent`,
      { invoiceId: estimate._id },
    );
  }

  invoicePaid(userId: string, invoice: any) {
    return this.sendAlert(
      userId,
      AlertType.INVOICE_PAID,
      "Invoice paid",
      `Invoice #${invoice.number} has been paid`,
      { invoiceId: invoice._id },
    );
  }

  estimateAccepted(userId: string, estimate: any) {
    return this.sendAlert(
      userId,
      AlertType.ESTIMATE_ACCEPTED,
      "Estimate accepted",
      `Estimate #${estimate.number} is accepted`,
      { estimateId: estimate._id },
    );
  }

  estimateRejected(userId: string, estimate: any) {
    return this.sendAlert(
      userId,
      AlertType.ESTIMATE_REJECTED,
      "Estimate rejected",
      `Estimate #${estimate.number} is rejected`,
      { estimateId: estimate._id },
    );
  }

  invoiceDue(userId: string, invoice: any) {
    return this.sendAlert(
      userId,
      AlertType.INVOICE_DUE,
      "Invoice due",
      `Invoice #${invoice.number} is due today`,
      { invoiceId: invoice._id },
    );
  }

  invoiceOverdue(userId: string, invoice: any) {
    return this.sendAlert(
      userId,
      AlertType.INVOICE_OVERDUE,
      "Invoice overdue",
      `Invoice #${invoice.number} is overdue`,
      { invoiceId: invoice._id },
    );
  }
}
