package com.mosquito.project.service;

import com.mosquito.project.persistence.entity.NotificationEntity;
import com.mosquito.project.persistence.repository.NotificationRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 通知服务
 * 已持久化到数据库
 */
@Service
public class NotificationService {

    private final NotificationRepository notificationRepository;

    public NotificationService(NotificationRepository notificationRepository) {
        this.notificationRepository = notificationRepository;
    }

    /**
     * 获取用户通知列表
     */
    public Map<String, Object> getNotifications(Long userId, Integer page, Integer size, String type, Boolean isRead, String keyword) {
        int pageNum = page != null && page >= 0 ? page : 0;
        int pageSize = size != null && size > 0 ? size : 20;
        Pageable pageable = PageRequest.of(pageNum, pageSize, Sort.by(Sort.Direction.DESC, "createdAt"));

        Page<NotificationEntity> notificationPage;
        boolean hasKeyword = keyword != null && !keyword.isBlank();

        if (hasKeyword) {
            // 有关键词搜索时
            if (type != null && !type.isEmpty() && isRead != null) {
                notificationPage = notificationRepository.findByUserIdAndTypeAndKeyword(userId, type, keyword, pageable);
            } else if (type != null && !type.isEmpty()) {
                notificationPage = notificationRepository.findByUserIdAndTypeAndKeyword(userId, type, keyword, pageable);
            } else if (isRead != null) {
                notificationPage = notificationRepository.findByUserIdAndIsReadAndKeyword(userId, isRead, keyword, pageable);
            } else {
                notificationPage = notificationRepository.findByUserIdAndKeyword(userId, keyword, pageable);
            }
        } else {
            // 无关键词搜索时
            if (type != null && !type.isEmpty()) {
                notificationPage = notificationRepository.findByUserIdAndType(userId, type, pageable);
            } else if (isRead != null) {
                notificationPage = notificationRepository.findByUserIdAndIsRead(userId, isRead, pageable);
            } else {
                notificationPage = notificationRepository.findByUserId(userId, pageable);
            }
        }

        List<Map<String, Object>> list = notificationPage.getContent().stream()
                .map(this::toMap)
                .toList();

        Map<String, Object> result = new HashMap<>();
        result.put("data", list);
        result.put("total", notificationPage.getTotalElements());
        result.put("page", pageNum);
        result.put("size", pageSize);
        result.put("totalPages", notificationPage.getTotalPages());
        return result;
    }

    /**
     * 获取用户未读通知数量
     */
    public long getUnreadCount(Long userId) {
        return notificationRepository.countByUserIdAndIsReadFalse(userId);
    }

    /**
     * 创建通知
     */
    public NotificationEntity createNotification(NotificationEntity notification) {
        return notificationRepository.save(notification);
    }

    /**
     * 标记通知为已读
     */
    @Transactional
    public boolean markAsRead(Long notificationId, Long userId) {
        return notificationRepository.findById(notificationId)
                .filter(n -> n.getUserId().equals(userId))
                .map(n -> {
                    n.setIsRead(true);
                    n.setReadAt(LocalDateTime.now());
                    notificationRepository.save(n);
                    return true;
                })
                .orElse(false);
    }

    /**
     * 标记所有通知为已读
     */
    @Transactional
    public int markAllAsRead(Long userId) {
        return notificationRepository.markAllAsReadByUserId(userId, LocalDateTime.now());
    }

    /**
     * 删除通知
     */
    public boolean deleteNotification(Long notificationId, Long userId) {
        return notificationRepository.findById(notificationId)
                .filter(n -> n.getUserId().equals(userId))
                .map(n -> {
                    notificationRepository.delete(n);
                    return true;
                })
                .orElse(false);
    }

    /**
     * 批量标记为已读
     */
    @Transactional
    public int batchMarkAsRead(List<Long> notificationIds, Long userId) {
        int count = 0;
        for (Long id : notificationIds) {
            if (markAsRead(id, userId)) {
                count++;
            }
        }
        return count;
    }

    /**
     * 实体转Map
     */
    private Map<String, Object> toMap(NotificationEntity entity) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", entity.getId());
        map.put("title", entity.getTitle());
        map.put("content", entity.getContent());
        map.put("type", entity.getType());
        map.put("relatedId", entity.getRelatedId());
        map.put("relatedType", entity.getRelatedType());
        map.put("isRead", entity.getIsRead());
        map.put("readAt", entity.getReadAt());
        map.put("createdAt", entity.getCreatedAt() != null ? entity.getCreatedAt().toString() : null);
        return map;
    }
}
