package repositories

import (
	"context"
	"fmt"
	"primesys_email/src/db"
	"primesys_email/src/models"
	"primesys_email/src/utils"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

const reportEmailQueueLogCollection = "report_email_queue_log"

// InsertReportEmailQueueLog inserts the log of one division mail when its sending starts
func InsertReportEmailQueueLog(ctx context.Context, log *models.ReportEmailQueueLog) (bson.ObjectID, error) {

	result, err := db.Database().
		Collection(reportEmailQueueLogCollection).
		InsertOne(ctx, log)
	if err != nil {
		return bson.ObjectID{}, err
	}

	id, ok := result.InsertedID.(bson.ObjectID)
	if !ok {
		return bson.ObjectID{}, fmt.Errorf("report email queue log id is not an object id")
	}

	return id, nil
}

// FinishReportEmailQueueLog saves the result of the division mail
func FinishReportEmailQueueLog(ctx context.Context, id bson.ObjectID, status models.ReportEmailStatus, sentTo string, errMsg string) error {

	update := bson.M{
		"$set": bson.M{
			"status":        status,
			"sent_to":       sentTo,
			"error_message": errMsg,
			"finished_at":   utils.CurrentISTEpoch(),
		},
	}

	result, err := db.Database().
		Collection(reportEmailQueueLogCollection).
		UpdateOne(ctx, bson.M{"_id": id}, update)
	if err != nil {
		return err
	}

	if result.MatchedCount == 0 {
		return fmt.Errorf("report email queue log %s not found", id.Hex())
	}

	return nil
}

// IsReportEmailSent is true when the report of the division for the device type and report date
// was already mailed (a SENT log of the same process type exists)
func IsReportEmailSent(ctx context.Context, divisionId string, deviceTypeId int, reportDate int64, processType models.ProcessType) (bool, error) {

	filter := bson.M{
		"division_id":    divisionId,
		"device_type_id": deviceTypeId,
		"report_date":    reportDate,
		"process_type":   processType,
		"status":         models.EmailSent,
	}

	count, err := db.Database().
		Collection(reportEmailQueueLogCollection).
		CountDocuments(ctx, filter, options.Count().SetLimit(1))
	if err != nil {
		return false, err
	}

	return count > 0, nil
}
