package com.zioinfo.kintex.work.notification;

import com.zioinfo.kintex.auth.KintexPrincipal;
import com.zioinfo.kintex.common.PageResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 알림 서비스 — 발송 채널 단일화(§7-6). 도메인 모듈은 직접 발송 대신 {@link #notify}를 호출한다.
 * (WebSocket 실시간 푸시는 config.WebSocketConfig 토픽으로 별도 배선.)
 */
@Service
public class NotificationService {

    private final NotificationMapper mapper;

    public NotificationService(NotificationMapper mapper) {
        this.mapper = mapper;
    }

    /** 공통 알림 발행(도메인 모듈용). NOTI_TYPE: APPROVAL/DEADLINE/MESSAGE/SYSTEM. */
    @Transactional
    public String notify(String recipientId, String eventId, String notiType,
                         String title, String message, String link) {
        String id = "no-" + UUID.randomUUID().toString().substring(0, 12);
        Map<String, Object> p = new HashMap<>();
        p.put("id", id);
        p.put("recipientId", recipientId);
        p.put("eventId", eventId);
        p.put("notiType", notiType);
        p.put("title", title);
        p.put("message", message);
        p.put("link", link);
        mapper.insert(p);
        return id;
    }

    public PageResponse<NotificationDto> list(KintexPrincipal principal, boolean unreadOnly,
                                              int page, int size) {
        int pg = Math.max(page, 0);
        int s = size <= 0 ? 20 : Math.min(size, 200);
        Map<String, Object> q = new HashMap<>();
        q.put("userId", principal.userId());
        q.put("unreadOnly", unreadOnly);
        q.put("size", s);
        q.put("offset", pg * s);
        List<Map<String, Object>> rows = mapper.listForUser(q);
        long total = unreadOnly ? mapper.unreadCount(principal.userId()) : rows.size();
        return PageResponse.of(rows.stream().map(NotificationService::toDto).toList(), pg, s, total);
    }

    public long unreadCount(KintexPrincipal principal) {
        return mapper.unreadCount(principal.userId());
    }

    @Transactional
    public void markRead(KintexPrincipal principal, String id) {
        mapper.markRead(id, principal.userId());
    }

    @Transactional
    public void markAllRead(KintexPrincipal principal) {
        mapper.markAllRead(principal.userId());
    }

    @Transactional
    public void delete(KintexPrincipal principal, String id) {
        mapper.delete(id, principal.userId());
    }

    private static NotificationDto toDto(Map<String, Object> r) {
        return new NotificationDto(str(r.get("id")), str(r.get("recipientId")), str(r.get("eventId")),
                str(r.get("notiType")), str(r.get("title")), str(r.get("message")), str(r.get("link")),
                str(r.get("readAt")), str(r.get("createdAt")));
    }
    private static String str(Object o) { return o == null ? null : String.valueOf(o); }
}
