package de.oaa.xxx.social;

import de.oaa.xxx.mail.Email;
import de.oaa.xxx.mail.MailService;
import de.oaa.xxx.mail.MailTemplateService;
import org.springframework.beans.factory.annotation.Value;
import de.oaa.xxx.social.entity.MessageCause;
import de.oaa.xxx.social.entity.MessageEntity;
import de.oaa.xxx.social.entity.NotificationPreferenceEntity;
import de.oaa.xxx.social.repository.MessageRepository;
import de.oaa.xxx.social.repository.NotificationPreferenceRepository;
import de.oaa.xxx.user.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

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

@Service
public class SystemMessageService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SystemMessageService.class);

    private final MessageRepository messageRepository;
    private final NotificationPreferenceRepository preferenceRepository;
    private final UserRepository userRepository;
    private final SseService sseService;
    private final MailService mailService;
    private final MailTemplateService mailTemplateService;

    @Value("${app.base-url:http://localhost:8080}")
    private String baseUrl;

    public SystemMessageService(MessageRepository messageRepository,
                                NotificationPreferenceRepository preferenceRepository,
                                UserRepository userRepository,
                                SseService sseService,
                                MailService mailService,
                                MailTemplateService mailTemplateService) {
        this.messageRepository = messageRepository;
        this.preferenceRepository = preferenceRepository;
        this.userRepository = userRepository;
        this.sseService = sseService;
        this.mailService = mailService;
        this.mailTemplateService = mailTemplateService;
    }

    /**
     * Sendet eine Systemnachricht unter Berücksichtigung der Benachrichtigungseinstellungen des Empfängers.
     */
    public void send(UUID senderId, UUID receiverId, String text, String targetUrl, MessageCause cause) {
        if (senderId == null || receiverId == null) return;

        NotificationPreferenceEntity pref = preferenceRepository
                .findByUserIdAndCause(receiverId, cause)
                .orElseGet(() -> NotificationPreferenceEntity.defaultFor(receiverId, cause));

        // FRIENDREQUEST, INVITATION und DATE_INTEREST sind immer nur in-app, kein E-Mail
        boolean sendInApp = cause == MessageCause.FRIENDREQUEST || cause == MessageCause.INVITATION
                || cause == MessageCause.DATE_INTEREST || pref.isInApp();

        if (sendInApp) {
            MessageEntity msg = new MessageEntity();
            msg.setMessageId(UUID.randomUUID());
            msg.setSenderId(senderId);
            msg.setReceiverId(receiverId);
            msg.setText(text);
            msg.setSentAt(LocalDateTime.now());
            msg.setSystemMessage(true);
            msg.setMessageCause(cause);
            if (targetUrl != null) msg.setTargetUrl(targetUrl);
            messageRepository.save(msg);

            long unread = messageRepository.countByReceiverIdAndSystemMessageAndReadAtIsNull(receiverId, true);
            sseService.push(receiverId, "NOTIFICATION", Map.of("unreadCount", unread, "text", text));
        }

        if (pref.isEmail() && cause != MessageCause.INVITATION && cause != MessageCause.DATE_INTEREST) {
            userRepository.findById(receiverId).ifPresent(user -> {
                try {
                    Email email = new Email();
                    email.setEmailAdresse(user.getEmail());
                    email.setTitel(causeTitel(cause));
                    email.setText(mailTemplateService.buildNotificationMail(user.getName(), text, targetUrl, baseUrl));
                    mailService.send(email);
                } catch (Exception e) {
                    LOGGER.error("E-Mail-Benachrichtigung fehlgeschlagen für userId={}: {}", receiverId, e.getMessage());
                }
            });
        }
    }

    /**
     * Benachrichtigt den Empfänger per SSE, dass sich seine Einladungsliste geändert hat,
     * ohne eine In-App-Nachricht oder E-Mail zu erstellen.
     */
    public void pushInvitationUpdate(UUID receiverId) {
        if (receiverId == null) return;
        sseService.push(receiverId, "INVITATION", java.util.Map.of());
    }

    private String causeTitel(MessageCause cause) {
        return switch (cause) {
            case INVITATION    -> "XXX The Game – Neue Einladung";
            case GAME_STATE    -> "XXX The Game – Spielstatus-Änderung";
            case EMERGENCY     -> "XXX The Game – ⚠️ Notfall";
            case FRIENDREQUEST -> "XXX The Game – Neue Freundschaftsanfrage";
            case SUPPORT       -> "xXx Sphere – Nachricht vom Support";
            case DATE_INTEREST -> "xXx Sphere – Interesse an deinem Date";
        };
    }

}
