package com.iqser.red.service.persistence.management.v1.processor.service.persistence;

import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

import jakarta.transaction.Transactional;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.entity.notification.NotificationEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.NotificationRepository;
import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AddNotificationRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.notification.EmailNotificationType;

import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;

@Service
@RequiredArgsConstructor
public class NotificationPersistenceService {

    private final NotificationRepository notificationRepository;

    private final NotificationPreferencesPersistenceService notificationPreferencesPersistenceService;

    private final NotificationEmailService notificationEmailService;


    public boolean hasNewNotificationsSince(String userId, OffsetDateTime since) {

        notificationPreferencesPersistenceService.initializePreferencesIfNotExists(userId);
        return notificationRepository.hasInAppNotificationForUser(userId, since.truncatedTo(ChronoUnit.MILLIS)) > 0;
    }


    @SneakyThrows
    @Transactional
    public void insertNotification(AddNotificationRequest addNotificationRequest) {

        var notification = new NotificationEntity();
        BeanUtils.copyProperties(addNotificationRequest, notification);
        notification.setCreationDate(OffsetDateTime.now());

        var notificationPreferences = notificationPreferencesPersistenceService.getOrCreateNotificationPreferences(addNotificationRequest.getUserId());
        if (!notificationPreferences.isInAppNotificationsEnabled() || !notificationPreferences.getInAppNotifications().contains(notification.getNotificationType())) {
            notification.setSoftDeleted(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
        }

        if (notificationPreferences.isEmailNotificationsEnabled() && notificationPreferences.getEmailNotifications()
                .contains(notification.getNotificationType()) && notificationPreferences.getEmailNotificationType() == EmailNotificationType.DAILY) {
            notificationEmailService.sendNotificationEmail(notification.getUserId(), EmailNotificationType.DAILY, List.of(notification));
        }

        notificationRepository.save(notification);
    }


    @Transactional
    public void setSeenDate(String userId, long notificationId, OffsetDateTime seenDate) {

        int countUpdate = notificationRepository.setSeenDate(userId, notificationId, seenDate);
        if (countUpdate == 0) {
            throw new NotFoundException("Notification not found");
        }
    }


    @Transactional
    public void setReadDate(String userId, long notificationId, OffsetDateTime readDate) {

        int countUpdate = notificationRepository.setReadDate(userId, notificationId, readDate);
        if (countUpdate == 0) {
            throw new NotFoundException("Notification not found");
        }
    }


    @Transactional
    public void softDelete(String userId, long notificationId) {

        int countUpdate = notificationRepository.softDelete(userId, notificationId, OffsetDateTime.now());
        if (countUpdate == 0) {
            throw new NotFoundException("Notification not found");
        }
    }


    @Transactional
    public void hardDelete(long notificationId) {

        notificationRepository.deleteById(notificationId);
    }


    public List<NotificationEntity> getNotificationsForEmailSummary(String userId, OffsetDateTime from, OffsetDateTime to) {

        return notificationRepository.findEmailNotificationsForUserId(userId, from, to);
    }


    public List<NotificationEntity> getNotifications(String userId, boolean includeSeen) {

        notificationPreferencesPersistenceService.initializePreferencesIfNotExists(userId);
        if (includeSeen) {
            return notificationRepository.findAppNotificationsForUser(userId);
        } else {
            return notificationRepository.findUnseenNotificationsForUser(userId);
        }

    }

}
