package com.iqser.red.persistence.service.v1.external.api.impl.controller;

import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.READ_NOTIFICATIONS;
import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.UPDATE_NOTIFICATIONS;

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

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.NotificationPersistenceService;
import com.knecon.fforesight.databasetenantcommons.providers.utils.MagicConverter;
import com.iqser.red.service.persistence.service.v1.api.external.resource.NotificationResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.NotificationResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSONPrimitive;
import com.iqser.red.service.persistence.service.v1.api.shared.model.notification.Notification;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class NotificationController implements NotificationResource {

    private final NotificationPersistenceService notificationPersistenceService;


    @Override
    @PreAuthorize("hasAuthority('" + READ_NOTIFICATIONS + "')")
    public JSONPrimitive<Boolean> hasNewNotificationsSince(@RequestBody JSONPrimitive<OffsetDateTime> since) {

        return JSONPrimitive.of(notificationPersistenceService.hasNewNotificationsSince(KeycloakSecurity.getUserId(), since.getValue()));
    }

    @PreAuthorize("hasAuthority('" + UPDATE_NOTIFICATIONS + "')")
    public void toggleNotificationSeen(@RequestBody List<String> notificationIds, @RequestParam(SET_SEEN_PARAM) boolean setSeen) {

        notificationIds.stream().map(Long::valueOf).forEach(notificationId -> {
            if (setSeen) {
                notificationPersistenceService.setSeenDate(KeycloakSecurity.getUserId(), notificationId, OffsetDateTime.now());
            } else {
                notificationPersistenceService.setSeenDate(KeycloakSecurity.getUserId(), notificationId, null);
            }
        });
    }

    @PreAuthorize("hasAuthority('" + UPDATE_NOTIFICATIONS + "')")
    public void toggleNotificationRead(@RequestBody List<String> notificationIds, @RequestParam(SET_READ_PARAM) boolean setRead) {

        notificationIds.stream().map(Long::valueOf).forEach(notificationId -> {
            if (setRead) {
                notificationPersistenceService.setReadDate(KeycloakSecurity.getUserId(), notificationId, OffsetDateTime.now());
            } else {
                notificationPersistenceService.setReadDate(KeycloakSecurity.getUserId(), notificationId, null);
            }
        });
    }

    @PreAuthorize("hasAuthority('" + UPDATE_NOTIFICATIONS + "')")
    public void delete(@RequestBody List<String> notificationIds) {

        notificationIds.stream().map(Long::valueOf).forEach(notificationId -> {
            notificationPersistenceService.softDelete(KeycloakSecurity.getUserId(), notificationId);
        });
    }

    @PreAuthorize("hasAuthority('" + READ_NOTIFICATIONS + "')")
    public NotificationResponse getNotifications(@RequestParam(INCLUDE_SEEN_PARAM) boolean includeSeen) {

        var notifications = MagicConverter.convert(notificationPersistenceService.getNotifications(KeycloakSecurity.getUserId(), includeSeen), Notification.class);
        return NotificationResponse.builder().notifications(notifications).build();
    }

}
