package com.zioinfo.kintex.work.message;

import com.zioinfo.kintex.auth.KintexPrincipal;
import com.zioinfo.kintex.common.PageResponse;
import com.zioinfo.kintex.common.error.ApiException;
import com.zioinfo.kintex.common.error.ErrorCode;
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;

/** 쪽지 서비스 — 발송(수신/참조), 수신함/발신함, 읽음 처리, 삭제(수신자 소프트). */
@Service
public class MessageService {

    private final MessageMapper mapper;

    public MessageService(MessageMapper mapper) {
        this.mapper = mapper;
    }

    @Transactional
    public String send(KintexPrincipal principal, MessageSendRequest req) {
        String id = "msg-" + UUID.randomUUID().toString().substring(0, 12);
        Map<String, Object> m = new HashMap<>();
        m.put("id", id);
        m.put("senderId", principal.userId());
        m.put("senderName", principal.displayName());
        m.put("title", req.title());
        m.put("content", req.content());
        mapper.insertMessage(m);
        addRecipients(id, req.recipientIds(), "RECV");
        addRecipients(id, req.refIds(), "REF");
        return id;
    }

    private void addRecipients(String messageId, List<String> ids, String recvType) {
        if (ids == null) {
            return;
        }
        for (String rid : ids) {
            if (rid == null || rid.isBlank()) {
                continue;
            }
            Map<String, Object> r = new HashMap<>();
            r.put("id", "mr-" + UUID.randomUUID().toString().substring(0, 12));
            r.put("messageId", messageId);
            r.put("recipientId", rid);
            r.put("recvType", recvType);
            mapper.insertRecipient(r);
        }
    }

    public PageResponse<MessageDto> inbox(KintexPrincipal principal, int page, int size) {
        int p = Math.max(page, 0);
        int s = size <= 0 ? 20 : Math.min(size, 200);
        List<Map<String, Object>> rows = mapper.inbox(principal.userId(), s, p * s);
        long total = mapper.inboxCount(principal.userId());
        return PageResponse.of(rows.stream().map(MessageService::toDto).toList(), p, s, total);
    }

    public PageResponse<MessageDto> sent(KintexPrincipal principal, int page, int size) {
        int p = Math.max(page, 0);
        int s = size <= 0 ? 20 : Math.min(size, 200);
        List<Map<String, Object>> rows = mapper.sent(principal.userId(), s, p * s);
        return PageResponse.of(rows.stream().map(MessageService::toDto).toList(), p, s, rows.size());
    }

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

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

    @Transactional
    public void delete(KintexPrincipal principal, String messageId) {
        if (mapper.deleteForRecipient(messageId, principal.userId()) == 0) {
            throw new ApiException(ErrorCode.NOT_FOUND);
        }
    }

    private static MessageDto toDto(Map<String, Object> r) {
        return new MessageDto(str(r.get("id")), str(r.get("senderId")), str(r.get("senderName")),
                str(r.get("title")), str(r.get("content")), str(r.get("recvType")),
                str(r.get("readAt")), str(r.get("createdAt")));
    }
    private static String str(Object o) { return o == null ? null : String.valueOf(o); }
}
