package shop.alien.store.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import shop.alien.entity.second.SecondGoodsRecord;
import shop.alien.entity.second.vo.SecondUserViolationDetailVo;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.LifeUserViolationDto;
import shop.alien.entity.store.excelVo.LifeUserViolationExcelVO;
import shop.alien.entity.store.excelVo.util.ExcelGenerator;
import shop.alien.entity.store.vo.LifeUserViolationVo;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.mapper.*;
import shop.alien.mapper.second.SecondGoodsRecordMapper;
import shop.alien.mapper.second.SecondUserViolationMapper;
import shop.alien.store.config.WebSocketProcess;
import shop.alien.store.service.*;
import shop.alien.store.util.AiUserViolationUtils;
import shop.alien.store.util.FunctionMagic;
import shop.alien.store.util.ai.AiReportReviewUtil;
import shop.alien.util.ali.AliOSSUtil;
import shop.alien.util.common.EnumUtil;
import shop.alien.util.type.LifeNoticeUtil;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


/**
 * <p>
 * 用户举报 服务实现类
 * </p>
 *
 * @author ssk
 * @since 2025-04-29
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LifeUserViolationServiceImpl extends ServiceImpl<LifeUserViolationMapper, LifeUserViolation> implements LifeUserViolationService {

    private final LifeUserViolationMapper lifeUserViolationMapper;

    private final LifeUserMapper lifeUserMapper;

    private final StoreUserMapper storeUserMapper;

    private final LifeUserService lifeUserService;

    private final StoreUserService storeUserService;

    private final LifeUserDynamicsService lifeUserDynamicsService;

    private final StoreCommentService storeCommentService;

    private final LifeCommentMapper lifeCommentMapper;

    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeNoticeUtil lifeNoticeUtil;

    private final WebSocketProcess webSocketProcess;

    private final AliOSSUtil aliOSSUtil;

    private final LifeUserDynamicsMapper lifeUserDynamicsMapper;

    private final StoreCommentMapper storeCommentMapper;

    private final SecondGoodsRecordMapper secondGoodsRecordMapper;
    private final StoreImgService storeImgService;

    private final AiUserViolationUtils aiUserViolationUtils;
    private final CommonCommentMapper commonCommentMapper;
    private final AiReportReviewUtil aiReportReviewUtil;



    @Autowired
    private SecondUserViolationMapper mapper;

    @Value("${spring.web.resources.excel-path}")
    private String excelPath;

    @Value("${spring.web.resources.excel-generate-path}")
    private String excelGeneratePath;

    @Override
    public int reporting(LifeUserViolation lifeuserViolation) throws Exception {
        try {
            lifeuserViolation.setProcessingStatus("0");
            lifeuserViolation.setDeleteFlag(0);
            if ("4".equals(lifeuserViolation.getReportContextType())) {
                LambdaQueryWrapper<SecondGoodsRecord> goodsWrapper = new LambdaQueryWrapper<>();
                goodsWrapper.eq(SecondGoodsRecord::getGoodsId, lifeuserViolation.getBusinessId());
                goodsWrapper.eq(SecondGoodsRecord::getGoodsStatus, "3");
                goodsWrapper.orderByDesc(SecondGoodsRecord::getCreatedTime);
                goodsWrapper.last(" limit 1 ");
                SecondGoodsRecord goodsRecord = secondGoodsRecordMapper.selectOne(goodsWrapper);
                if (null != goodsRecord) lifeuserViolation.setBusinessId(goodsRecord.getId());
            }
            int result = lifeUserViolationMapper.insert(lifeuserViolation);
            if (result > 0) {
                // 调用AI异步审核，审核完成后会自动发送审核结果通知
                aiReportReviewUtil.reviewReport(lifeuserViolation.getId(), lifeuserViolation.getReportContextType());
                return result;
            }
        } catch (Exception e) {
            log.error("LifeUserViolationServiceImpl_reporting Error Stack={}", e.getMessage());
            throw new Exception(e);
        }
        return 0;
    }

    private LifeNotice getLifeNotice(LifeUserViolation lifeuserViolation) {
        String phoneId = null;

        LifeNotice lifeNotice = new LifeNotice();
        lifeNotice.setSenderId("system");
        lifeNotice.setBusinessId(lifeuserViolation.getId());
        lifeNotice.setTitle("举报通知");
        JSONObject jsonObject = new JSONObject();
        String message = "平台已受理，感谢您的反馈！";

        String reportContextType = lifeuserViolation.getReportContextType();
        String reportUserId = lifeuserViolation.getReportingUserId();

        if ("1".equals(lifeuserViolation.getReportingUserType())) {
            StoreUser storeUsers = storeUserMapper.selectById(reportUserId);
            phoneId = "store_"+storeUsers.getPhone();
        } else {
            LifeUser lifeUsers = lifeUserMapper.selectById(reportUserId);
            phoneId = "user_"+lifeUsers.getUserPhone();
        }

        lifeNotice.setReceiverId(phoneId);

        if(StringUtils.isNotEmpty(reportContextType) && "1,2,3".contains(reportContextType)){
            String violationType = StringUtils.isNotEmpty(lifeuserViolation.getViolationType())?lifeuserViolation.getViolationType():"13";
            String violationText = EnumUtil.getStatusValue(Integer.parseInt(violationType));

            String storeOrUserName = "";
            // 查询被举报用户信息
            String reportedUserId = lifeuserViolation.getReportedUserId();
            if ("1".equals(lifeuserViolation.getReportedUserType())) {
                StoreUser storeUser = storeUserMapper.selectById(reportedUserId);
                storeOrUserName = storeUser.getNickName();
            } else {
                LifeUser lifeUser = lifeUserMapper.selectById(reportedUserId);
                storeOrUserName = lifeUser.getUserName();
            }

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat simpleDateFormats = new SimpleDateFormat("yyyy-MM-dd");
            String storeDate = simpleDateFormat.format(new Date());

            switch (reportContextType) {
                case "1":
                    message = "您在" + storeDate + "举报用户“" + storeOrUserName + "”，涉嫌"+violationText+"，已提交至平台审核，1-3个工作日会将审核结果发送到您应用内的消息-通知中，请注意查收。";
                    break;
                case "2":
                    String dynamicsId = lifeuserViolation.getDynamicsId();
                    String dynamicsDate = simpleDateFormat.format(new Date());
                    if(StringUtils.isNotEmpty(dynamicsId)){
                        LifeUserDynamics lifeUserDynamics = lifeUserDynamicsMapper.selectById(dynamicsId);
                        dynamicsDate = simpleDateFormats.format(lifeUserDynamics.getCreatedTime());
                    }
                    message = "您在" + storeDate + "举报用户“" + storeOrUserName + "”在"+dynamicsDate+"发布的动态，涉嫌"+violationText+"，已提交至平台审核，1-3个工作日会将审核结果发送到您应用内的消息-通知中，请注意查收。";
                    break;
                case "3":
                    String commonId = lifeuserViolation.getCommentId();
                    String commonDate = simpleDateFormat.format(new Date());
                    if(StringUtils.isNotEmpty(commonId)){
                        StoreComment storeComment  = storeCommentMapper.selectById(commonId);
                        commonDate = simpleDateFormats.format(storeComment.getCreatedTime());
                    }
                    message = "您在" + storeDate + "举报用户“" + storeOrUserName + "”在"+commonDate+"发布的评论，涉嫌"+violationText+"，已提交至平台审核，1-3个工作日会将审核结果发送到您应用内的消息-通知中，请注意查收。";
                    break;
            }
        }

        jsonObject.put("title", "平台已受理");
        jsonObject.put("message", message);
        lifeNotice.setContext(jsonObject.toJSONString());
        lifeNotice.setNoticeType(1);
        return lifeNotice;
    }

    private LifeNotice getLifeReportedNotice(LifeUserViolation lifeuserViolation) throws Exception {

        // 查询被举报用户信息
        String reportUserId = lifeuserViolation.getReportedUserId();
        String phoneId = "";
        LifeNotice lifeNotice = new LifeNotice();

        if ("1".equals(lifeuserViolation.getReportedUserType())) {
            StoreUser storeUser = storeUserMapper.selectById(reportUserId);
            phoneId = storeUser.getPhone();
            lifeNotice.setReceiverId("store_" + phoneId);
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(reportUserId);
            phoneId = lifeUser.getUserPhone();
            lifeNotice.setReceiverId("user_" + phoneId);

        }
        if (StringUtils.isEmpty(phoneId)){
            return null;
        }
        String violationText = EnumUtil.getStatusValue(Integer.parseInt(lifeuserViolation.getViolationType()));

        lifeNotice.setSenderId("system");
        lifeNotice.setBusinessId(lifeuserViolation.getId());
        lifeNotice.setTitle("举报通知");
        JSONObject jsonObject = new JSONObject();
        String message = "";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String storeDate = simpleDateFormat.format(new Date());
        String reportContextType = lifeuserViolation.getReportContextType();

        if(StringUtils.isNotEmpty(reportContextType) && reportContextType.equals("1")){
            message = "您在" + storeDate + "被举报涉嫌"+violationText+"，平台将会进行核实。如确实存在违规行为，平台将禁用您的账号**天，到期后账号可恢复使用，应用内的环境需要我们共同维护。";
        } else {
            return null;
        }
        jsonObject.put("message", message);
        lifeNotice.setContext(jsonObject.toJSONString());
        lifeNotice.setNoticeType(1);
        return lifeNotice;
    }

    @Override
    public Map<String, Object> reportListByUserId(String userId) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        LambdaUpdateWrapper<LifeUserViolation> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LifeUserViolation::getReportingUserId, userId).orderByDesc(LifeUserViolation::getCreatedTime);
        List<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(wrapper);
        List<LifeUserViolation> filteredViolations = lifeUserViolations.stream().filter(violation -> !"0".equals(violation.getProcessingStatus())).collect(Collectors.toList());
        List<LifeUserViolationVo> lifeUserViolationsVo = new ArrayList<>();
        for (LifeUserViolation violation : filteredViolations) {
            LifeUserViolationVo vo = new LifeUserViolationVo();
            BeanUtils.copyProperties(violation, vo);
            lifeUserViolationsVo.add(vo);
        }
        lifeUserViolationsVo.forEach(lifeUserViolationVo -> {
            lifeUserViolationVo.setReportResultNotification("举报结果通知");
        });
        if (!lifeUserViolations.isEmpty()) {
            resultMap.put("createTime", lifeUserViolations.get(0).getCreatedTime());
            resultMap.put("data", lifeUserViolationsVo);
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> reportListById(String id) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        LifeUserViolationVo lifeUserViolationVo = new LifeUserViolationVo();
        LifeUserViolation lifeUserViolation = lifeUserViolationMapper.selectById(id);
        //商户或者用户名称
        String storeOrUserName;
        if ("1".equals(lifeUserViolation.getReportedUserType())) {
            StoreUser storeUser = storeUserMapper.selectById(lifeUserViolation.getReportedUserId());
            storeOrUserName = storeUser.getName();
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(lifeUserViolation.getReportedUserId());
            storeOrUserName = lifeUser.getUserName();
        }
        resultMap.put("message", lifeUserViolation.getProcessingStatus() != null ? lifeUserViolation.getProcessingStatus() : "");
        lifeUserViolationVo.setReportObject(storeOrUserName);
        lifeUserViolationVo.setViolationType(lifeUserViolation.getViolationType());
        lifeUserViolationVo.setReportEvidenceImg(lifeUserViolation.getReportEvidenceImg());
        lifeUserViolationVo.setCreatedTime(lifeUserViolation.getCreatedTime());
        resultMap.put("reportDetail", lifeUserViolationVo);
        LifeUserViolationVo lifeUserViolationVo2 = new LifeUserViolationVo();
        lifeUserViolationVo2.setProcessingStatus(lifeUserViolation.getProcessingStatus());
        lifeUserViolationVo2.setProcessingTime(lifeUserViolation.getProcessingTime());
        resultMap.put("processStatus", lifeUserViolationVo);
        return resultMap;
    }

    @Override
    public IPage<LifeUserViolationDto> getViolationPage(int page, int size, String nickName, String phone, String processingStatus) {
        IPage<LifeUserViolationVo> pageRequest = new Page<>(page, size);
        QueryWrapper<LifeUserViolationVo> queryWrapper = new QueryWrapper<>();

        // 动态查询条件
        queryWrapper.like(StringUtils.isNotEmpty(nickName), "nick_name", nickName)
                .like(StringUtils.isNotEmpty(phone), "phone", phone);

        if (StringUtils.isNotEmpty(processingStatus)) {
            queryWrapper.eq("processing_status", processingStatus);
        }

        queryWrapper.orderByDesc("updated_time");

        IPage<LifeUserViolationVo> resultPage = lifeUserViolationMapper.getViolationPage(pageRequest, queryWrapper);

        return resultPage.convert(e -> {
            LifeUserViolationDto dto = new LifeUserViolationDto();
            BeanUtils.copyProperties(e, dto);

            // 处理举报凭证图片
            if (Objects.nonNull(e.getReportEvidenceImg())) {
                List<String> imageList = Arrays.stream(e.getReportEvidenceImg().split(","))
                        .map(String::trim)
                        .filter(StringUtils::isNotEmpty)
                        .collect(Collectors.toList());

                if (!imageList.isEmpty()) {
                    dto.setImage(imageList.get(0));
                    dto.setImageList(imageList);
                }
            }

            dto.setNickname(e.getNickName());
            return dto;
        });
    }

    @Override
    public void approve(int id, String processingStatus, String reportResult) {
        if(id==0 || StringUtils.isBlank(processingStatus)){
            return;
        }
        LifeUserViolation v = lifeUserViolationMapper.selectById(id);
        v.setProcessingStatus(processingStatus);
        v.setProcessingTime(new Date());
        v.setReportResult(reportResult);

        // 举报时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat simpleDateFormats = new SimpleDateFormat("yyyy-MM-dd");
        String violationTime = simpleDateFormat.format(v.getCreatedTime());
        // 被举报人信息
        String reportedUserName = "";
        if(StringUtils.isNotEmpty(v.getReportedUserId())){
            if (v.getReportedUserType().equals("1")) {
                StoreUser storeUser = storeUserMapper.selectById(v.getReportedUserId());
                if(storeUser != null){
                    reportedUserName = storeUser.getNickName();
                }
            } else{
                LifeUser lifeUser = lifeUserMapper.selectById(v.getReportedUserId());
                if(lifeUser != null) {
                    reportedUserName = lifeUser.getUserName();
                }
            }
        }
        // 被举报动态信息
        String dynamicsId = v.getDynamicsId();
        String dynamicsDate = simpleDateFormats.format(new Date());
        if(StringUtils.isNotEmpty(dynamicsId)){
            LifeUserDynamics lifeUserDynamics = lifeUserDynamicsMapper.selectById(dynamicsId);
            dynamicsDate = simpleDateFormats.format(lifeUserDynamics.getCreatedTime());
        }
        // 被举报评论信息
        String commonId = v.getCommentId();
        String commonDate = simpleDateFormats.format(new Date());
        if(StringUtils.isNotEmpty(commonId)){
            StoreComment storeComment  = storeCommentMapper.selectById(commonId);
            commonDate = simpleDateFormats.format(storeComment.getCreatedTime());
        }

        // 举报通知信息
        String message = "";
        // 被举报通知信息
        String reportedMessage = "";
        String title = "";
        if (processingStatus.equals("1")) {
            // 通过
            if (v.getReportContextType().equals("1")) {
                // 用户
                message = "您在"+violationTime+"举报用户“"+reportedUserName+"”，涉嫌违法违规，经核实，确实存在违规行为，平台已将用户禁用，感谢您为此做出的贡献。";
                title = "用户举报成功通知";
            }
            if (v.getReportContextType().equals("2")) {
                // 动态
                message = "您在"+violationTime+"举报用户“"+reportedUserName+"”在"+dynamicsDate+"发布的动态，涉嫌违法违规，经核实，确实存在违规行为，平台已将此动态下架，感谢您为此做出的贡献";
                reportedMessage = "您在"+dynamicsDate+"发布的动态，经核实，确实存在违规行为，平台已将此动态下架，应用内的环境需要我们共同维护";
                lifeUserDynamicsService.removeById(v.getDynamicsId());
                title = "动态举报成功通知";
            }
            if (v.getReportContextType().equals("3")) {
                // 评论
                if (v.getReportedUserType().equals("1")) {
                    // 商户
                    message = "您在"+violationTime+"举报用户“"+reportedUserName+"”在"+commonDate+"发布的评论，涉嫌违法违规，经核实，确实存在违规行为，平台已将此评论下架，感谢您为此做出的贡献。";
                    storeCommentService.removeById(v.getCommentId());
                } else {
                    // 用户
                    message = "您在"+violationTime+"举报用户“"+reportedUserName+"”在"+commonDate+"发布的评论，涉嫌违法违规，经核实，确实存在违规行为，平台已将此评论下架，感谢您为此做出的贡献。";
                    lifeCommentMapper.deleteById(v.getCommentId());
                }
                reportedMessage = "您在"+commonDate+"发布的评论，经核实，确实存在违规行为，平台已将此评论下架，应用内的环境需要我们共同维护。";
                title = "评论举报成功通知";
            }
        } else {
            // 驳回
            switch (v.getReportContextType()) {
                case "1":
                    message = "您在"+violationTime+"举报用户“"+reportedUserName+"”，涉嫌违法违规，经核实，不存在违规行为，感谢您为此做出的贡献。";
                    title = "用户举报失败通知";
                    break;
                case "2":
                    message = "您在"+violationTime+"举报用户“"+reportedUserName+"”在"+dynamicsDate+"发布的动态，涉嫌违法违规，经核实，不存在违规行为，感谢您为此做出的贡献。";
                    title = "动态举报失败通知";
                    break;
                case "3":
                    message = "您在"+violationTime+"举报用户“"+reportedUserName+"”在"+commonDate+"发布的评论，涉嫌违法违规，经核实，不存在违规行为，感谢您为此做出的贡献。";
                    title = "评论举报失败通知";
                    break;
            }
        }
        lifeUserViolationMapper.updateById(v);
        LifeNotice LifeMessage = new LifeNotice();
        com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
        jsonObject.put("message", message);
        LifeMessage.setContext(jsonObject.toJSONString());
        LifeMessage.setSenderId("system");
        LifeMessage.setIsRead(0);
        LifeMessage.setTitle(title);
        LifeMessage.setNoticeType(1);
        LifeMessage.setBusinessId(id);
        if (v.getReportingUserType().equals("1")) {
            // M
            StoreUser storeUser = storeUserService.getOne(new QueryWrapper<StoreUser>().eq("id", v.getReportingUserId()));
            LifeMessage.setReceiverId("store_" + storeUser.getPhone());
        } else {
            // U
            LifeUser lifeUser = lifeUserService.getOne(new QueryWrapper<LifeUser>().eq("id", v.getReportingUserId()));
            LifeMessage.setReceiverId("user_" + lifeUser.getUserPhone());

        }
        lifeNoticeUtil.fillUserTypeAndRefId(LifeMessage);
        lifeNoticeMapper.insert(LifeMessage);

        WebSocketVo websocketVo = new WebSocketVo();
        websocketVo.setSenderId("system");
        websocketVo.setReceiverId(LifeMessage.getReceiverId());
        websocketVo.setCategory("notice");
        websocketVo.setNoticeType("1");
        websocketVo.setIsRead(0);
        websocketVo.setText(com.alibaba.fastjson2.JSONObject.from(LifeMessage).toJSONString());
        try {
            webSocketProcess.sendMessage(LifeMessage.getReceiverId(), com.alibaba.fastjson2.JSONObject.from(websocketVo).toJSONString());
        } catch (Exception e) {
            log.error("LifeUserViolationServiceImpl_approve Error Stack={}", e.getMessage());
        }


        // 被举报通知
        if(StringUtils.isNotEmpty(reportedMessage)) {
            LifeNotice reportedLifeMessage = new LifeNotice();
            com.alibaba.fastjson2.JSONObject jsonObjectReported = new com.alibaba.fastjson2.JSONObject();
            jsonObjectReported.put("message", reportedMessage);
            reportedLifeMessage.setContext(jsonObjectReported.toJSONString());
            reportedLifeMessage.setSenderId("system");
            reportedLifeMessage.setIsRead(0);
            reportedLifeMessage.setTitle(title);
            reportedLifeMessage.setNoticeType(1);
            reportedLifeMessage.setBusinessId(id);
            if (v.getReportedUserType().equals("1")) {
                // M
                StoreUser storeUser = storeUserService.getOne(new QueryWrapper<StoreUser>().eq("id", v.getReportedUserId()));
                reportedLifeMessage.setReceiverId("store_" + storeUser.getPhone());
            } else {
                // U
                LifeUser lifeUser = lifeUserService.getOne(new QueryWrapper<LifeUser>().eq("id", v.getReportedUserId()));
                reportedLifeMessage.setReceiverId("user_" + lifeUser.getUserPhone());
            }
            lifeNoticeUtil.fillUserTypeAndRefId(reportedLifeMessage);
            lifeNoticeMapper.insert(reportedLifeMessage);

            WebSocketVo websocketVoReported = new WebSocketVo();
            websocketVoReported.setSenderId("system");
            websocketVoReported.setReceiverId(reportedLifeMessage.getReceiverId());
            websocketVoReported.setCategory("notice");
            websocketVoReported.setNoticeType("1");
            websocketVoReported.setIsRead(0);
            websocketVoReported.setText(com.alibaba.fastjson2.JSONObject.from(reportedLifeMessage).toJSONString());
            try {
                webSocketProcess.sendMessage(reportedLifeMessage.getReceiverId(), com.alibaba.fastjson2.JSONObject.from(websocketVoReported).toJSONString());
            } catch (Exception e) {
                log.error("LifeUserViolationServiceImpl_reported_approve Error Stack={}", e.getMessage());
            }
        }

    }

    @Override
    public LifeUserViolationDto byId(Integer id) {
        LifeUserViolation entity = lifeUserViolationMapper.selectById(id);
        if (entity == null) return null;
        LifeUserViolationDto dto = new LifeUserViolationDto();
        BeanUtils.copyProperties(entity, dto);
        if (Objects.nonNull(entity.getReportEvidenceImg())) {
            List<String> list = Arrays.stream(entity.getReportEvidenceImg().split(",")).map(String::trim).collect(Collectors.toList());
            dto.setImageList(list);
        }
        // 处理举报人信息
        FunctionMagic.handleUserInfo(dto.getReportingUserType(), dto.getReportingUserId(), storeId -> storeUserService.getOne(FunctionMagic.idQueryWrapper(storeId)), lifeId -> lifeUserService.getOne(FunctionMagic.idQueryWrapper(lifeId)), user -> {
            if (user instanceof StoreUser) {
                StoreUser su = (StoreUser) user;
                dto.setNickname(su.getNickName());
                dto.setPhone(su.getPhone());
            } else if (user instanceof LifeUser) {
                LifeUser lu = (LifeUser) user;
                dto.setNickname(lu.getUserName());
                dto.setPhone(lu.getUserPhone());
            }
        });
        // 处理被举报人信息
        FunctionMagic.handleUserInfo(dto.getReportedUserType(), dto.getReportedUserId(), storeId -> storeUserService.getOne(FunctionMagic.idQueryWrapper(storeId)), lifeId -> lifeUserService.getOne(FunctionMagic.idQueryWrapper(lifeId)), user -> {
            if (user instanceof StoreUser) {
                dto.setAccount(((StoreUser) user).getPhone());
            } else if (user instanceof LifeUser) {
                dto.setAccount(((LifeUser) user).getUserPhone());
            }
        });
        return dto;
    }

    @Override
    public LifeUserViolationDto byIdNotice(Integer id) {
        LifeNotice lifeNotice = lifeNoticeMapper.selectById(id);
        LifeUserViolationDto dto = byId(lifeNotice.getBusinessId());
        dto.setLifeNotice(lifeNotice.getContext());
        return dto;
    }

    @Override
    public String exportExcel(String nickName, String phone, String processingStatus) throws IOException {
        QueryWrapper<LifeUserViolationVo> queryWrapper = new QueryWrapper<>();

        // 基础查询条件（与 getViolationPage 保持一致）
        queryWrapper.eq("luv.delete_flag", 0)
                .in("luv.report_context_type", Arrays.asList("1", "2", "3"));

        // 动态查询条件
        queryWrapper.like(StringUtils.isNotEmpty(nickName), "ui.nick_name", nickName)
                .like(StringUtils.isNotEmpty(phone), "ui.phone", phone);
        if (StringUtils.isNotEmpty(processingStatus)) {
            queryWrapper.eq("luv.processing_status", processingStatus);
        }
        queryWrapper.orderByDesc("luv.updated_time");

        List<LifeUserViolationVo> violationList = lifeUserViolationMapper.getViolationList(queryWrapper);
        
        // 如果查询结果为空，返回空列表生成的Excel
        if (CollectionUtils.isEmpty(violationList)) {
            log.warn("导出Excel时查询结果为空，nickName={}, phone={}, processingStatus={}", nickName, phone, processingStatus);
        }

        // 日期格式化器（复用）
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        
        // 使用Stream API进行转换，提高性能和可读性
        AtomicInteger serialNumber = new AtomicInteger(1);
        List<LifeUserViolationExcelVO> excelDataList = violationList.stream()
                .map(vo -> convertToExcelVO(vo, serialNumber.getAndIncrement(), dateTimeFormatter))
                .collect(Collectors.toList());

        // 生成Excel文件
        String fileName = UUID.randomUUID().toString().replace("-", "");
        String filePath = ExcelGenerator.generateExcel(
                excelPath + excelGeneratePath + fileName + ".xlsx", 
                excelDataList, 
                LifeUserViolationExcelVO.class);
        
        // 上传到OSS并返回URL
        return aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
    }

    /**
     * 将 LifeUserViolationVo 转换为 LifeUserViolationExcelVO
     *
     * @param vo 源对象
     * @param serialNumber 序号
     * @param formatter 日期格式化器
     * @return Excel VO对象
     */
    private LifeUserViolationExcelVO convertToExcelVO(LifeUserViolationVo vo, int serialNumber, DateTimeFormatter formatter) {
        LifeUserViolationExcelVO excelVO = new LifeUserViolationExcelVO();
        BeanUtils.copyProperties(vo, excelVO);
        
        excelVO.setId(serialNumber);
        excelVO.setNickname(vo.getNickName());
        
        // 处理举报凭证图片（安全分割，避免数组越界）
        if (StringUtils.isNotEmpty(vo.getReportEvidenceImg())) {
            String[] imageParts = vo.getReportEvidenceImg().split(",");
            if (imageParts.length > 0 && StringUtils.isNotEmpty(imageParts[0])) {
                excelVO.setReportEvidenceImg(imageParts[0].trim());
            }
        }
        
        // 处理举报内容类型
        if (StringUtils.isNotEmpty(vo.getReportContextType())) {
            try {
                excelVO.setReportContextType(FunctionMagic.getContext(vo.getReportContextType()));
            } catch (Exception e) {
                log.warn("转换举报内容类型失败，reportContextType={}, error={}", vo.getReportContextType(), e.getMessage());
                excelVO.setReportContextType(vo.getReportContextType());
            }
        }
        
        // 处理举报理由
        if (StringUtils.isNotEmpty(vo.getViolationType())) {
            try {
                excelVO.setViolationType(FunctionMagic.violation(vo.getViolationType()));
            } catch (Exception e) {
                log.warn("转换举报理由失败，violationType={}, error={}", vo.getViolationType(), e.getMessage());
                excelVO.setViolationType(vo.getViolationType());
            }
        }
        
        // 处理处理状态
        if (StringUtils.isNotEmpty(vo.getProcessingStatus())) {
            try {
                excelVO.setProcessingStatus(FunctionMagic.status(vo.getProcessingStatus()));
            } catch (Exception e) {
                log.warn("转换处理状态失败，processingStatus={}, error={}", vo.getProcessingStatus(), e.getMessage());
                excelVO.setProcessingStatus(vo.getProcessingStatus());
            }
        }
        
        // 格式化创建时间
        if (Objects.nonNull(vo.getCreatedTime())) {
            try {
                String formattedTime = vo.getCreatedTime().toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDateTime()
                        .format(formatter);
                excelVO.setCreatedTime(formattedTime);
            } catch (Exception e) {
                log.warn("格式化创建时间失败，createdTime={}, error={}", vo.getCreatedTime(), e.getMessage());
            }
        }
        
        // 格式化处理时间
        if (Objects.nonNull(vo.getProcessingTime())) {
            try {
                String formattedProcessingTime = vo.getProcessingTime().toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDateTime()
                        .format(formatter);
                excelVO.setProcessingTime(formattedProcessingTime);
            } catch (Exception e) {
                log.warn("格式化处理时间失败，processingTime={}, error={}", vo.getProcessingTime(), e.getMessage());
            }
        }
        
        return excelVO;
    }

    @Override
    public String level(UserLoginInfo userLoginInfo) {
        if (null == userLoginInfo) {
            return "O";
        }
        String type = userLoginInfo.getType();
        LambdaQueryWrapper<LifeUserViolation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LifeUserViolation::getReportContextType, "1").eq(LifeUserViolation::getReportedUserId, userLoginInfo.getUserId());
        if (Objects.equals(type, "store")) {
            // 商户
            wrapper.eq(LifeUserViolation::getReportedUserType, 1);
        } else if (Objects.equals(type, "user")) {
            // 用户
            wrapper.eq(LifeUserViolation::getReportedUserType, 2);
        }
        int count = Optional.ofNullable(lifeUserViolationMapper.selectList(wrapper)).map(List::size).orElse(0);
        if (count == 0) return "O";
        if (count >= 15) return "E";
        if (count >= 10) return "D";
        if (count >= 6) return "C";
        if (count >= 3) return "B";
        return "A";
    }

    @Override
    public IPage<LifeUserViolationDto> getAllViolationPage(int page, int size, String nickName, String phone, String processingStatus, String startTime, String endTime, String reportContextType) {
        IPage<LifeUserViolationVo> pageRequest = new Page<>(page, size);
        QueryWrapper<LifeUserViolationVo> queryWrapper = new QueryWrapper<>();

        // 动态查询条件
        queryWrapper.like(StringUtils.isNotEmpty(nickName), "nick_name", nickName)
                .like(StringUtils.isNotEmpty(phone), "phone", phone);

        if (StringUtils.isNotEmpty(processingStatus)) {
            queryWrapper.eq("processing_status", processingStatus);
        }

        if (StringUtils.isNotEmpty(reportContextType)) {
            queryWrapper.eq("report_context_type", reportContextType);
        }
        // 根据开始时间和结束时间过滤
        if (StringUtils.isNotEmpty(startTime)) {
            queryWrapper.ge("created_time", startTime);
        }
        if (StringUtils.isNotEmpty(endTime)) {
            queryWrapper.le("created_time", endTime);
        }
        queryWrapper.orderByDesc("updated_time");

        IPage<LifeUserViolationVo> resultPage = lifeUserViolationMapper.getAllViolationPage(pageRequest, queryWrapper);

        return resultPage.convert(e -> {
            LifeUserViolationDto dto = new LifeUserViolationDto();
            BeanUtils.copyProperties(e, dto);
            dto.setNickname(e.getNickName());
            return dto;
        });
    }


    @Override
    public SecondUserViolationDetailVo queryViolationDetail(Integer id, String reportContextType) {
        // 查询举报信息
        SecondUserViolationDetailVo item = mapper.getUserViolationDetailInfo(id);

        // 视频文件类型
        List<String> videoFileType = Arrays.asList("mp4", "avi", "mov", "wmv", "flv", "mkv");

        if ("2".equals(item.getReportContextType())) {
            LifeUserDynamics dynamicsInfo = lifeUserDynamicsMapper.selectAll(new LambdaQueryWrapper<LifeUserDynamics>()
                    .eq(LifeUserDynamics::getId, item.getDynamicsId())
                    .and(d -> d.eq(LifeUserDynamics::getDeleteFlag, 1)
                            .or(c-> c.eq(LifeUserDynamics::getDeleteFlag, 0))));
            item.setDynamicsInfo(dynamicsInfo);
            // 将逗号分隔的图片路径拆分成 List<String>
            if (dynamicsInfo != null && StringUtils.isNotEmpty(dynamicsInfo.getImagePath())) {
                List<String> imagePathList = Arrays.stream(dynamicsInfo.getImagePath().split(","))
                        .map(String::trim)
                        .filter(StringUtils::isNotEmpty)
                        .collect(Collectors.toList());
                // 如果包含视频，则过滤掉图片（视频封面/第一帧），只保留用户实际上传的视频
                boolean hasVideo = imagePathList.stream().anyMatch(url -> {
                    String ext = url.substring(url.lastIndexOf(".") + 1).toLowerCase();
                    return videoFileType.contains(ext);
                });
                if (hasVideo) {
                    imagePathList = imagePathList.stream().filter(url -> {
                        String ext = url.substring(url.lastIndexOf(".") + 1).toLowerCase();
                        return videoFileType.contains(ext);
                    }).collect(Collectors.toList());
                }
                item.setDynamicsImg(imagePathList);
            }
        }

        if ("3".equals(item.getReportContextType())) {
            // TODO: 处理评论类型
            CommonComment commonComment = commonCommentMapper.selectAll(new LambdaQueryWrapper<CommonComment>()
                    .eq(CommonComment::getId, item.getBusinessId()));


            item.setCommonCommentInfo(commonComment);

//            StoreComment commentInfo = storeCommentMapper.selectById(item.getBusinessId());
//            item.setCommentInfo(commentInfo);
            LifeUserDynamics dynamicsInfo = lifeUserDynamicsMapper.selectAll(new LambdaQueryWrapper<LifeUserDynamics>()
                    .eq(LifeUserDynamics::getId, commonComment.getSourceId())
                    .and(d -> d.eq(LifeUserDynamics::getDeleteFlag, 1)
                            .or(c-> c.eq(LifeUserDynamics::getDeleteFlag, 0))));
            item.setDynamicsInfo(dynamicsInfo);
            // 将逗号分隔的图片路径拆分成 List<String>
            if (dynamicsInfo != null && StringUtils.isNotEmpty(dynamicsInfo.getImagePath())) {
                List<String> imagePathList = Arrays.stream(dynamicsInfo.getImagePath().split(","))
                        .map(String::trim)
                        .filter(StringUtils::isNotEmpty)
                        .collect(Collectors.toList());
                // 如果包含视频，则过滤掉图片（视频封面/第一帧），只保留用户实际上传的视频
                boolean hasVideo = imagePathList.stream().anyMatch(url -> {
                    String ext = url.substring(url.lastIndexOf(".") + 1).toLowerCase();
                    return videoFileType.contains(ext);
                });
                if (hasVideo) {
                    imagePathList = imagePathList.stream().filter(url -> {
                        String ext = url.substring(url.lastIndexOf(".") + 1).toLowerCase();
                        return videoFileType.contains(ext);
                    }).collect(Collectors.toList());
                }
                item.setDynamicsImg(imagePathList);
            }
        }

        List<Map<String, Object>> list = new ArrayList<>();
        // 将逗号分隔的图片路径拆分成 List<String>
        if (item != null && StringUtils.isNotEmpty(item.getReportEvidenceImg())) {
            List<String> imagePathList = Arrays.stream(item.getReportEvidenceImg().split(","))
                    .map(String::trim)
                    .filter(StringUtils::isNotEmpty)
                    .collect(Collectors.toList());

            for (String imgUrl : imagePathList) {
                Map<String, Object> map = new HashMap<>();
                String fileType = imgUrl.substring(imgUrl.lastIndexOf(".") + 1);
                if (videoFileType.contains(fileType.toLowerCase())) {
                    map.put("type", "video");
                } else {
                    map.put("type", "image");
                }
                map.put("imgUrl", imgUrl);
                list.add(map);
            }

            // 如果包含视频，则过滤掉图片（视频封面），只保留用户实际上传的视频
            boolean hasVideo = list.stream().anyMatch(map -> "video".equals(map.get("type")));
            if (hasVideo) {
                list = list.stream().filter(map -> "video".equals(map.get("type"))).collect(Collectors.toList());
            }

            item.setImgList(list);
        }

        return item;
    }
}
