package com.jeesharp.business.member.support;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.member.application.MemberApplicationService;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.letter.core.LetterReceiverType;
import com.jeesharp.framework.letter.manage.vo.LetterInboxQueryVO;
import com.jeesharp.framework.letter.manage.vo.LetterInboxVO;
import com.jeesharp.framework.letter.service.LetterInboxService;
import com.jeesharp.framework.pojo.query.PageRespVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * C 端会员站内信适配：对接 {@code jeesharp-spring-boot-starter-letter}，并转换为历史消息中心 JSON 结构。
 *
 * @author jeesharp
 * @since 2026-07-13
 */
@Component
@AllArgsConstructor
public class MemberLetterInboxMobileSupport {

    private static final String RECEIVER_TYPE = LetterReceiverType.MEMBER.getCode();

    private final LetterInboxService letterInboxService;
    private final MemberApplicationService memberApplicationService;

    public Map<String, Object> list(String memberId, long page, long pageSize, Integer type, Integer isRead) {
        String tenantId = requireTenantId(memberId);
        LetterInboxQueryVO query = new LetterInboxQueryVO();
        query.setPageNo(page);
        query.setPageSize(pageSize);
        query.setIsRead(isRead);
        String msgType = mapTypeToMsgType(type);
        if (msgType != null) {
            query.setMsgType(msgType);
        }

        PageRespVO<LetterInboxVO> pageResp =
                letterInboxService.pageByReceiver(tenantId, RECEIVER_TYPE, memberId,query);
        long unread = letterInboxService.countUnreadByReceiver(tenantId, RECEIVER_TYPE, memberId);

        Map<String, Object> data = new LinkedHashMap<>();
        data.put("total", pageResp.getTotal() == null ? 0L : pageResp.getTotal());
        data.put("page", pageResp.getPageNo() == null ? page : pageResp.getPageNo());
        data.put("pageSize", pageResp.getPageSize() == null ? pageSize : pageResp.getPageSize());
        List<Map<String, Object>> list = pageResp.getRecords() == null
                ? List.of()
                : pageResp.getRecords().stream().map(this::toMobileRow).toList();
        data.put("list", list);
        data.put("unreadCount", unread);
        return data;
    }

    public Map<String, Object> detail(String memberId, String id) {
        String tenantId = requireTenantId(memberId);
        LetterInboxVO vo = letterInboxService.detailByReceiver(tenantId, RECEIVER_TYPE, memberId, id);
        return vo == null ? null : toMobileRow(vo);
    }

    public void markRead(String memberId, String id) {
        String tenantId = requireTenantId(memberId);
        letterInboxService.markReadByReceiver(tenantId, RECEIVER_TYPE, memberId, List.of(id));
    }

    public void markAllRead(String memberId) {
        String tenantId = requireTenantId(memberId);
        letterInboxService.markAllReadByReceiver(tenantId, RECEIVER_TYPE, memberId, null);
    }

    /**
     * 站内信模块暂未提供删除能力，保留接口兼容并静默成功。
     */
    public void delete(String memberId, String id) {
        requireTenantId(memberId);
        if (StrUtil.isBlank(id)) {
            throw new BizErrorException("消息不存在");
        }
    }

    /**
     * 站内信模块暂未提供清空已读能力，保留接口兼容并静默成功。
     */
    public void clearRead(String memberId) {
        requireTenantId(memberId);
    }

    public Map<String, Object> unreadSummary(String memberId) {
        String tenantId = requireTenantId(memberId);
        long count = letterInboxService.countUnreadByReceiver(tenantId, RECEIVER_TYPE, memberId);
        Map<String, Long> grouped =
                letterInboxService.countUnreadGroupByMsgType(tenantId, RECEIVER_TYPE, memberId);

        Map<String, Object> data = new LinkedHashMap<>();
        data.put("count", count);
        Map<String, Long> byType = new LinkedHashMap<>();
        byType.put("1", sumByMsgTypes(grouped, "SYSTEM"));
        byType.put("2", sumByMsgTypes(grouped, "ORDER", "TRADE", "BUSINESS"));
        byType.put("3", sumByMsgTypes(grouped, "ACTIVITY", "MARKETING"));
        data.put("byType", byType);
        return data;
    }

    public long countUnread(String memberId) {
        String tenantId = requireTenantId(memberId);
        return letterInboxService.countUnreadByReceiver(tenantId, RECEIVER_TYPE, memberId);
    }

    private String requireTenantId(String memberId) {
        if (StrUtil.isBlank(memberId)) {
            throw new BizErrorException("请先登录");
        }
        String tenantId = memberApplicationService.getMemberTenantId(memberId);
        if (StrUtil.isBlank(tenantId)) {
            throw new BizErrorException("租户信息缺失，无法读取消息");
        }
        return tenantId;
    }

    private Map<String, Object> toMobileRow(LetterInboxVO vo) {
        Map<String, Object> row = new LinkedHashMap<>();
        row.put("id", vo.getId());
        row.put("type", mapMsgTypeToType(vo.getMsgType()));
        row.put("title", StrUtil.nullToEmpty(vo.getTitle()));
        row.put("content", StrUtil.nullToEmpty(vo.getContent()));
        row.put("icon", "");
        row.put("image", "");
        String linkUrl = StrUtil.nullToEmpty(vo.getLinkUrl());
        row.put("link", linkUrl);
        row.put("linkType", resolveLinkType(linkUrl));
        row.put("linkParams", "");
        row.put("isRead", Boolean.TRUE.equals(vo.getIsRead()) ? 1 : 0);
        row.put("createTime", StrUtil.nullToEmpty(vo.getCreateDate()));
        row.put("readTime", "");
        return row;
    }

    private static int resolveLinkType(String linkUrl) {
        if (StrUtil.isBlank(linkUrl)) {
            return 3;
        }
        String trimmed = linkUrl.trim();
        if (trimmed.startsWith("/") || trimmed.startsWith("pages/")) {
            return 1;
        }
        if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
            return 2;
        }
        return 1;
    }

    private static String mapTypeToMsgType(Integer type) {
        if (type == null) {
            return null;
        }
        return switch (type) {
            case 1 -> "SYSTEM";
            case 2 -> "ORDER";
            case 3 -> "ACTIVITY";
            default -> null;
        };
    }

    private static int mapMsgTypeToType(String msgType) {
        if (StrUtil.isBlank(msgType)) {
            return 0;
        }
        return switch (msgType.trim().toUpperCase()) {
            case "SYSTEM" -> 1;
            case "ORDER", "TRADE", "BUSINESS" -> 2;
            case "ACTIVITY", "MARKETING" -> 3;
            default -> 0;
        };
    }

    private static long sumByMsgTypes(Map<String, Long> grouped, String... msgTypes) {
        if (grouped == null || grouped.isEmpty()) {
            return 0L;
        }
        long sum = 0L;
        for (String msgType : msgTypes) {
            for (Map.Entry<String, Long> entry : grouped.entrySet()) {
                if (entry.getKey() != null && entry.getKey().equalsIgnoreCase(msgType)) {
                    sum += entry.getValue() == null ? 0L : entry.getValue();
                }
            }
        }
        return sum;
    }
}
