package de.assecutor.votianlt.messaging.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Envelope that wraps all messages sent through the messaging system.
 * Contains metadata for delivery tracking and acknowledgment.
 * This is a DTO class - not persisted to MongoDB.
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class MessageEnvelope {

    /**
     * Unique identifier for this message (UUID)
     */
    private String messageId;

    /**
     * Timestamp when the envelope was created
     */
    private LocalDateTime timestamp;

    /**
     * Target topic for this message
     */
    private String topic;

    /**
     * The actual message payload (can be any serializable object)
     */
    private Object payload;

    /**
     * Whether this message requires acknowledgment from the receiver
     */
    private boolean requiresAck;

    /**
     * Number of times this message has been retried
     */
    private int retryCount;

    /**
     * When this message expires and should no longer be delivered
     */
    private LocalDateTime expiresAt;

    /**
     * Additional metadata for the message
     */
    private Map<String, String> metadata;

    /**
     * Constructor for creating a new envelope with payload
     */
    public MessageEnvelope(String topic, Object payload, boolean requiresAck, LocalDateTime expiresAt) {
        this.messageId = UUID.randomUUID().toString();
        this.timestamp = LocalDateTime.now();
        this.topic = topic;
        this.payload = payload;
        this.requiresAck = requiresAck;
        this.retryCount = 0;
        this.expiresAt = expiresAt;
        this.metadata = new HashMap<>();
    }

    /**
     * Check if this message has expired
     */
    public boolean isExpired() {
        return expiresAt != null && LocalDateTime.now().isAfter(expiresAt);
    }

    /**
     * Increment the retry counter
     */
    public void incrementRetryCount() {
        this.retryCount++;
    }

    /**
     * Add metadata to the envelope
     */
    public void addMetadata(String key, String value) {
        if (this.metadata == null) {
            this.metadata = new HashMap<>();
        }
        this.metadata.put(key, value);
    }
}
