package de.oaa.xxx.social.repository;

import de.oaa.xxx.social.entity.MessageEntity;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

public interface MessageRepository extends JpaRepository<MessageEntity, UUID> {

    // ── DM queries (systemMessage = false) ────────────────────────────────────

    @Query("SELECT m FROM MessageEntity m WHERE ((m.senderId = :userA AND m.receiverId = :userB) OR (m.senderId = :userB AND m.receiverId = :userA)) AND m.systemMessage = false ORDER BY m.sentAt DESC")
    List<MessageEntity> findConversation(@Param("userA") UUID userA, @Param("userB") UUID userB, Pageable pageable);

    @Query("SELECT m FROM MessageEntity m WHERE ((m.senderId = :userA AND m.receiverId = :userB) OR (m.senderId = :userB AND m.receiverId = :userA)) AND m.systemMessage = false AND m.sentAt < :before ORDER BY m.sentAt DESC")
    List<MessageEntity> findConversationBefore(@Param("userA") UUID userA, @Param("userB") UUID userB, @Param("before") LocalDateTime before, Pageable pageable);

    @Query("SELECT m FROM MessageEntity m WHERE ((m.senderId = :userA AND m.receiverId = :userB) OR (m.senderId = :userB AND m.receiverId = :userA)) AND m.systemMessage = false AND m.sentAt > :after ORDER BY m.sentAt ASC")
    List<MessageEntity> findConversationAfter(@Param("userA") UUID userA, @Param("userB") UUID userB, @Param("after") LocalDateTime after);

    @Query("SELECT m FROM MessageEntity m WHERE (m.senderId = :userId OR m.receiverId = :userId) AND m.systemMessage = false ORDER BY m.sentAt DESC")
    List<MessageEntity> findAllByUser(@Param("userId") UUID userId);

    @Query("SELECT COUNT(m) FROM MessageEntity m WHERE m.receiverId = :userId AND m.readAt IS NULL AND m.systemMessage = false")
    long countUnread(@Param("userId") UUID userId);

    @Modifying
    @Transactional
    @Query("UPDATE MessageEntity m SET m.readAt = :now WHERE m.senderId = :partnerId AND m.receiverId = :userId AND m.readAt IS NULL AND m.systemMessage = false")
    void markAsRead(@Param("userId") UUID userId, @Param("partnerId") UUID partnerId, @Param("now") LocalDateTime now);

    @Query("SELECT COUNT(m) > 0 FROM MessageEntity m WHERE ((m.senderId = :a AND m.receiverId = :b) OR (m.senderId = :b AND m.receiverId = :a)) AND m.systemMessage = false")
    boolean conversationExists(@Param("a") UUID a, @Param("b") UUID b);

    @Modifying
    @Transactional
    @Query("DELETE FROM MessageEntity m WHERE (m.senderId = :a AND m.receiverId = :b) OR (m.senderId = :b AND m.receiverId = :a)")
    void deleteConversation(@Param("a") UUID a, @Param("b") UUID b);

    // ── Notification queries (systemMessage = true) ───────────────────────────

    /** Ungelesene zuerst, dann nach sentAt absteigend, max. 10 Einträge. */
    @Query("SELECT m FROM MessageEntity m WHERE m.receiverId = :receiverId AND m.systemMessage = true " +
           "ORDER BY CASE WHEN m.readAt IS NULL THEN 0 ELSE 1 END, m.sentAt DESC")
    List<MessageEntity> findNotificationsForUser(@Param("receiverId") UUID receiverId, Pageable pageable);

    long countByReceiverIdAndSystemMessageAndReadAtIsNull(UUID receiverId, boolean systemMessage);

    @Modifying
    @Transactional
    @Query("UPDATE MessageEntity m SET m.readAt = :now WHERE m.receiverId = :userId AND m.systemMessage = true AND m.readAt IS NULL")
    void markAllNotificationsAsRead(@Param("userId") UUID userId, @Param("now") LocalDateTime now);

    @Modifying
    @Transactional
    @Query("UPDATE MessageEntity m SET m.readAt = :now WHERE m.messageId = :id AND m.receiverId = :userId AND m.readAt IS NULL")
    void markNotificationAsRead(@Param("id") UUID id, @Param("userId") UUID userId, @Param("now") LocalDateTime now);
}
