package com.njcn.rdms.module.system.service.feedback;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.annotations.VisibleForTesting;
import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.framework.common.util.object.BeanUtils;
import com.njcn.rdms.module.system.controller.admin.feedback.vo.FeedbackPageReqVO;
import com.njcn.rdms.module.system.controller.admin.feedback.vo.FeedbackRespVO;
import com.njcn.rdms.module.system.controller.admin.feedback.vo.FeedbackSaveReqVO;
import com.njcn.rdms.module.system.controller.admin.feedback.vo.FeedbackStatRespVO;
import com.njcn.rdms.module.system.controller.admin.feedback.vo.FeedbackStatusReqVO;
import com.njcn.rdms.module.system.controller.admin.feedback.vo.FeedbackUpdateReqVO;
import com.njcn.rdms.module.system.dal.dataobject.feedback.FeedbackDO;
import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO;
import com.njcn.rdms.module.system.dal.mysql.feedback.FeedbackMapper;
import com.njcn.rdms.module.system.enums.DictTypeConstants;
import com.njcn.rdms.module.system.service.dict.DictDataService;
import com.njcn.rdms.module.system.service.user.AdminUserService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.FEEDBACK_NOT_FOUND;

/**
 * 用户意见反馈 Service 实现类
 */
@Service
public class FeedbackServiceImpl implements FeedbackService {

    @Resource
    private FeedbackMapper feedbackMapper;
    @Resource
    private AdminUserService adminUserService;
    @Resource
    private DictDataService dictDataService;

    @Override
    public Long createFeedback(FeedbackSaveReqVO reqVO) {
        FeedbackDO feedback = BeanUtils.toBean(reqVO, FeedbackDO.class);
        feedback.setStatus(1); // 默认「待处理」，不信任前端传入
        feedbackMapper.insert(feedback);
        return feedback.getId();
    }

    @Override
    public void updateFeedback(FeedbackUpdateReqVO reqVO) {
        // 临时功能，后端不鉴权（仅过 token）；编辑权限由前端按钮可见性控制
        validateFeedbackExists(reqVO.getId());
        // 只更新内容字段：toBean 不带 status/creator，updateById 不会动它们（status 走专用接口、creator 为审计字段）；
        // attachmentUrls/contact 传 null 也会落库清空（DO 上 FieldStrategy.ALWAYS）
        FeedbackDO update = BeanUtils.toBean(reqVO, FeedbackDO.class);
        feedbackMapper.updateById(update);
    }

    @Override
    public PageResult<FeedbackRespVO> getFeedbackPage(FeedbackPageReqVO reqVO) {
        PageResult<FeedbackDO> pageResult = feedbackMapper.selectPage(reqVO);
        return new PageResult<>(buildRespList(pageResult.getList()), pageResult.getTotal());
    }

    @Override
    public FeedbackRespVO getFeedback(Long id) {
        FeedbackDO feedback = validateFeedbackExists(id);
        return buildRespList(Collections.singletonList(feedback)).get(0);
    }

    @Override
    public void updateFeedbackStatus(Long id, FeedbackStatusReqVO reqVO) {
        validateFeedbackExists(id);
        FeedbackDO update = new FeedbackDO();
        update.setId(id);
        update.setStatus(reqVO.getStatus());
        feedbackMapper.updateById(update);
    }

    @Override
    public void deleteFeedback(Long id) {
        // 临时功能，后端不鉴权（仅过 token）；删除权限由前端按钮可见性控制
        validateFeedbackExists(id);
        feedbackMapper.deleteById(id);
    }

    @Override
    public FeedbackStatRespVO getFeedbackStat() {
        // 一次性全量加载（软删自动排除），内存按两个维度聚合：同一数据快照天然保证 total 与各维度计数之和一致
        List<FeedbackDO> all = feedbackMapper.selectList();
        Map<Integer, Long> typeCountMap = all.stream()
                .filter(item -> item.getType() != null)
                .collect(Collectors.groupingBy(FeedbackDO::getType, Collectors.counting()));
        Map<Integer, Long> statusCountMap = all.stream()
                .filter(item -> item.getStatus() != null)
                .collect(Collectors.groupingBy(FeedbackDO::getStatus, Collectors.counting()));

        FeedbackStatRespVO stat = new FeedbackStatRespVO();
        stat.setTotal(all.size());
        // 按字典全集补零：无数据的码值也返回 count=0，保证消费端结构稳定，无需自己补零
        stat.setTypeCounts(dictCodes(DictTypeConstants.FEEDBACK_TYPE).stream()
                .map(code -> new FeedbackStatRespVO.TypeCount(code, countOf(typeCountMap, code)))
                .collect(Collectors.toList()));
        stat.setStatusCounts(dictCodes(DictTypeConstants.FEEDBACK_STATUS).stream()
                .map(code -> new FeedbackStatRespVO.StatusCount(code, countOf(statusCountMap, code)))
                .collect(Collectors.toList()));
        return stat;
    }

    /** 取字典某类型下全部码值（含停用项），顺序按字典 sort；非数字 value 跳过 */
    private List<Integer> dictCodes(String dictType) {
        return dictDataService.getDictDataListByDictType(dictType).stream()
                .map(dict -> parseDictValue(dict.getValue()))
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
    }

    private Integer countOf(Map<Integer, Long> countMap, Integer code) {
        return countMap.getOrDefault(code, 0L).intValue();
    }

    /** 字典 value 解析为整数码值；空 / 非数字返回 null，避免脏字典数据炸接口 */
    private Integer parseDictValue(String value) {
        if (StrUtil.isBlank(value)) {
            return null;
        }
        try {
            return Integer.valueOf(value.trim());
        } catch (NumberFormatException e) {
            return null;
        }
    }

    @VisibleForTesting
    public FeedbackDO validateFeedbackExists(Long id) {
        FeedbackDO feedback = feedbackMapper.selectById(id);
        if (feedback == null) {
            throw exception(FEEDBACK_NOT_FOUND);
        }
        return feedback;
    }

    /** DO 列表转 RespVO，并把 creator（user id 字符串）批量翻译成提交人姓名，避免逐行查库 */
    private List<FeedbackRespVO> buildRespList(List<FeedbackDO> list) {
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        Set<Long> userIds = list.stream()
                .map(feedback -> parseUserId(feedback.getCreator()))
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Long, AdminUserDO> userMap = adminUserService.getUserMap(userIds);
        return BeanUtils.toBean(list, FeedbackRespVO.class, resp -> {
            Long uid = parseUserId(resp.getCreator());
            AdminUserDO user = uid == null ? null : userMap.get(uid);
            resp.setCreatorName(user != null ? user.getNickname() : "");
        });
    }

    /** creator 是 String 形态的 user id，解析为 Long；空/非数字返回 null */
    private Long parseUserId(String creator) {
        if (StrUtil.isBlank(creator)) {
            return null;
        }
        try {
            return Long.valueOf(creator.trim());
        } catch (NumberFormatException e) {
            return null;
        }
    }

}
