package controller import ( "context" "encoding/json" "fmt" "log/slog" "net/http" "github.com/AFASystems/presence/internal/pkg/api/response" "github.com/AFASystems/presence/internal/pkg/model" "github.com/gorilla/mux" "github.com/segmentio/kafka-go" "gorm.io/gorm" ) func SendKafkaMessage(writer *kafka.Writer, value *model.ApiUpdate, context context.Context) error { valueStr, err := json.Marshal(&value) if err != nil { msg := fmt.Sprintf("error in encoding: %v", err) slog.Error(msg) return err } msg := kafka.Message{ Value: valueStr, } if err := writer.WriteMessages(context, msg); err != nil { msg := fmt.Sprintf("Error in sending kafka message: %v", err) slog.Error(msg) return err } return nil } func TrackerAdd(db *gorm.DB, writer *kafka.Writer, context context.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var tracker model.Tracker if err := json.NewDecoder(r.Body).Decode(&tracker); err != nil { response.BadRequest(w, "invalid request body") return } if err := db.WithContext(context).Create(&tracker).Error; err != nil { response.InternalError(w, "failed to create tracker", err) return } apiUpdate := model.ApiUpdate{ Method: "POST", ID: tracker.ID, MAC: tracker.MAC, } if err := SendKafkaMessage(writer, &apiUpdate, context); err != nil { slog.Error("error sending Kafka POST message", "err", err) response.InternalError(w, "failed to publish tracker update", err) return } response.JSON(w, http.StatusCreated, map[string]string{"status": "created"}) } } func TrackerList(db *gorm.DB, context context.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var list []model.Tracker if err := db.WithContext(context).Find(&list).Error; err != nil { response.InternalError(w, "failed to list trackers", err) return } response.JSON(w, http.StatusOK, list) } } func TrackerUpdate(db *gorm.DB, context context.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var tracker model.Tracker if err := json.NewDecoder(r.Body).Decode(&tracker); err != nil { response.BadRequest(w, "invalid request body") return } id := tracker.ID if err := db.WithContext(context).First(&model.Tracker{}, "id = ?", id).Error; err != nil { response.NotFound(w, "tracker not found") return } if err := db.WithContext(context).Save(&tracker).Error; err != nil { response.InternalError(w, "failed to update tracker", err) return } response.JSON(w, http.StatusOK, map[string]string{"status": "updated"}) } } func TrackerDelete(db *gorm.DB, writer *kafka.Writer, context context.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] var tracker model.Tracker if err := db.WithContext(context).First(&tracker, "id = ?", id).Error; err != nil { response.NotFound(w, "tracker not found") return } res := db.WithContext(context).Delete(&model.Tracker{}, "id = ?", id) if res.RowsAffected == 0 { response.NotFound(w, "tracker not found") return } if res.Error != nil { response.InternalError(w, "failed to delete tracker", res.Error) return } apiUpdate := model.ApiUpdate{ Method: "DELETE", MAC: tracker.MAC, } slog.Info("sending DELETE tracker message", "id", id) if err := SendKafkaMessage(writer, &apiUpdate, context); err != nil { slog.Error("error sending Kafka DELETE message", "err", err) response.InternalError(w, "failed to publish tracker deletion", err) return } response.JSON(w, http.StatusOK, map[string]string{"status": "deleted"}) } }