package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
import dev.lions.unionflow.server.api.enums.communication.MessageStatus;
import dev.lions.unionflow.server.api.enums.communication.MessageType;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;

/**
 * Entité Message pour le système de messagerie UnionFlow.
 * Représente un message individuel dans une conversation.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-16
 */
@Entity
@Table(name = "messages", indexes = {
    @Index(name = "idx_message_conversation", columnList = "conversation_id"),
    @Index(name = "idx_message_sender", columnList = "sender_id"),
    @Index(name = "idx_message_organisation", columnList = "organisation_id"),
    @Index(name = "idx_message_status", columnList = "status"),
    @Index(name = "idx_message_created", columnList = "date_creation"),
    @Index(name = "idx_message_deleted", columnList = "is_deleted")
})
@Getter
@Setter
public class Message extends BaseEntity {

    /**
     * Conversation parente
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "conversation_id", nullable = false)
    private Conversation conversation;

    /**
     * Expéditeur du message
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "sender_id", nullable = false)
    private Membre sender;

    /**
     * Nom de l'expéditeur (dénormalisé pour performance)
     */
    @Column(name = "sender_name", nullable = false, length = 255)
    private String senderName;

    /**
     * Avatar de l'expéditeur (dénormalisé)
     */
    @Column(name = "sender_avatar", length = 500)
    private String senderAvatar;

    /**
     * Contenu du message
     */
    @Column(name = "content", nullable = false, columnDefinition = "TEXT")
    private String content;

    /**
     * Type de message (INDIVIDUAL, BROADCAST, TARGETED, SYSTEM)
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "type", nullable = false, length = 20)
    private MessageType type;

    /**
     * Statut du message (SENT, DELIVERED, READ, FAILED)
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false, length = 20)
    private MessageStatus status;

    /**
     * Priorité du message (NORMAL, HIGH, URGENT)
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "priority", nullable = false, length = 20)
    private MessagePriority priority = MessagePriority.NORMAL;

    /**
     * IDs des destinataires (CSV pour targeted messages)
     */
    @Column(name = "recipient_ids", length = 2000)
    private String recipientIds;

    /**
     * Rôles destinataires (CSV pour role-based messaging)
     */
    @Column(name = "recipient_roles", length = 500)
    private String recipientRoles;

    /**
     * Organisation associée (optionnelle)
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "organisation_id")
    private Organisation organisation;

    /**
     * Date de lecture du message
     */
    @Column(name = "read_at")
    private LocalDateTime readAt;

    /**
     * Métadonnées additionnelles (JSON)
     */
    @Column(name = "metadata", columnDefinition = "TEXT")
    private String metadata;

    /**
     * Pièces jointes (CSV URLs)
     */
    @Column(name = "attachments", length = 2000)
    private String attachments;

    /**
     * Message édité
     */
    @Column(name = "is_edited", nullable = false)
    private Boolean isEdited = false;

    /**
     * Date d'édition
     */
    @Column(name = "edited_at")
    private LocalDateTime editedAt;

    /**
     * Message supprimé (soft delete)
     */
    @Column(name = "is_deleted", nullable = false)
    private Boolean isDeleted = false;

    /**
     * Marque le message comme lu
     */
    public void markAsRead() {
        this.status = MessageStatus.READ;
        this.readAt = LocalDateTime.now();
    }

    /**
     * Marque le message comme édité
     */
    public void markAsEdited() {
        this.isEdited = true;
        this.editedAt = LocalDateTime.now();
    }
}
