package com.fjhx.oa.service.daily.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.file.utils.ObsFileUtil;
import com.fjhx.oa.entity.daily.dto.DailyReportDto;
import com.fjhx.oa.entity.daily.dto.DailyReportSelectDto;
import com.fjhx.oa.entity.daily.po.DailyReport;
import com.fjhx.oa.entity.daily.po.DailyReportDetails;
import com.fjhx.oa.entity.daily.vo.DailyReportDetailsVo;
import com.fjhx.oa.entity.daily.vo.DailyReportVo;
import com.fjhx.oa.mapper.daily.DailyReportMapper;
import com.fjhx.oa.service.daily.DailyReportDetailsService;
import com.fjhx.oa.service.daily.DailyReportService;
import com.fjhx.socket.service.WebSocketServer;
import com.ruoyi.common.constant.StatusConstant;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 日报 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-04
 */
@DS(SourceConstant.OA)
@Service
public class DailyReportServiceImpl extends ServiceImpl<DailyReportMapper, DailyReport> implements DailyReportService {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @Autowired
    DailyReportDetailsService dailyReportDetailsService;

    @Override
    public Page<DailyReportVo> getPage(DailyReportSelectDto dto) {
        IWrapper<DailyReport> wrapper = getWrapper();
        wrapper.orderByDesc("date");
        Long userid = SecurityUtils.getUserId();
        wrapper.eq("dr", DailyReport::getCreateUser, dto.getSenderId());
        wrapper.groupBy("dr.id");

        if (ObjectUtil.isNotEmpty(dto.getDate())) {
            wrapper.apply("date_format(dr.create_time,'%Y-%m-%d') = date_format('" + sdf.format(dto.getDate()) + "','%Y-%m-%d')");
        }
        if (ObjectUtil.isNotEmpty(dto.getKeyword())) {
            wrapper.and(wrapper1 -> wrapper1.like(DailyReport::getCompletedWork, dto.getKeyword()).or().like(DailyReport::getUnfinishedWork, dto.getKeyword()).or().like(DailyReport::getIsVisibleToRecipient, dto.getKeyword()));
        }
        if (ObjectUtil.isNotEmpty(dto.getType())) {
            if (dto.getType() == 1) {
                //过滤我发出的日报
                wrapper.eq("dr.create_user", userid);
            } else if (dto.getType() == 2) {
                //过滤我收到的日报
                wrapper.eq("drd", DailyReportDetails::getRecipientId, userid);
            }
        } else {
            wrapper.and(q -> q.eq("dr", DailyReport::getCreateUser, userid).or().eq("drd", DailyReportDetails::getRecipientId, userid));
        }
        Page<DailyReportVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        UserUtil.assignmentNickName(page.getRecords(), DailyReport::getCreateUser, DailyReportVo::setUserName);
        return page;
    }

    @Override
    public DailyReportVo detail(Long id) {
        DailyReportVo result = baseMapper.detail(id);
        Map<Long, String> nickNameMapByIds = UserUtil.getNickNameMapByIds(Collections.singletonList(result.getCreateUser()));
        result.setUserName(nickNameMapByIds.get(result.getCreateUser()));

        // 添加已读记录
        dailyReportDetailsService.update(q -> q
                .eq(DailyReportDetails::getDailyReportId, id)
                .eq(DailyReportDetails::getRecipientId, SecurityUtils.getUserId())
                .eq(DailyReportDetails::getIsRead, StatusConstant.NO)
                .set(DailyReportDetails::getIsRead, StatusConstant.YES)
        );

        // 接收人列表
        List<DailyReportDetails> detailsList = dailyReportDetailsService.list(q -> q.eq(DailyReportDetails::getDailyReportId, id));
        List<DailyReportDetailsVo> detailsVoList = BeanUtil.copyToList(detailsList, DailyReportDetailsVo.class);
        UserUtil.assignmentNickName(detailsVoList, DailyReportDetails::getRecipientId, DailyReportDetailsVo::setRecipientName);
        result.setDetailsList(detailsVoList);

        return result;
    }

    @DSTransactional
    @Override
    public void add(DailyReportDto dailyReportDto) {
        this.save(dailyReportDto);
        //保存图片和附件信息
        ObsFileUtil.saveFile(dailyReportDto.getImgList(), dailyReportDto.getId(), 1);
        ObsFileUtil.saveFile(dailyReportDto.getAttachmentList(), dailyReportDto.getId(), 2);
        //保存接收人明细信息
        List<DailyReportDetails> dailyReportDetailsList = dailyReportDto.getDailyReportDetailsList();
        for (DailyReportDetails dailyReportDetails : dailyReportDetailsList) {
            dailyReportDetails.setIsRead(0);
            dailyReportDetails.setDailyReportId(dailyReportDto.getId());
        }
        dailyReportDetailsService.saveBatch(dailyReportDetailsList);
        //发送消息给所有待接收人
        Map<Long, String> nickNameMapByIds = UserUtil.getNickNameMapByIds(Arrays.asList(dailyReportDto.getCreateUser()));
        String userName = nickNameMapByIds.get(dailyReportDto.getCreateUser());
        Map<String, Object> msgMap = new HashMap<>();
        msgMap.put("businessId", dailyReportDto.getId());
        msgMap.put("msg", String.format("%s发布了新日志", userName));
        for (DailyReportDetails dailyReportDetails : dailyReportDetailsList) {
            WebSocketServer.sendInfo(dailyReportDetails.getRecipientId(), 1, msgMap);
        }
    }

    @DSTransactional
    @Override
    public void edit(DailyReportDto dailyReportDto) {
        this.updateById(dailyReportDto);
        //保存图片和附件信息
        ObsFileUtil.editFile(dailyReportDto.getImgList(), dailyReportDto.getId(), 1);
        ObsFileUtil.editFile(dailyReportDto.getAttachmentList(), dailyReportDto.getId(), 2);
        //处理接收人
        List<DailyReportDetails> dailyReportDetailsList = dailyReportDto.getDailyReportDetailsList();
        //先删除已经被删掉的接收人
        List<Long> recipientIds = dailyReportDetailsList.stream().map(DailyReportDetails::getRecipientId).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(recipientIds)) {
            dailyReportDetailsService.remove(q -> q.eq(DailyReportDetails::getDailyReportId, dailyReportDto.getId()).notIn(DailyReportDetails::getRecipientId, recipientIds));
        }
        //保存接收人明细信息
        for (DailyReportDetails dailyReportDetails : dailyReportDetailsList) {
            dailyReportDetails.setDailyReportId(dailyReportDto.getId());
        }
        dailyReportDetailsService.saveOrUpdateBatch(dailyReportDetailsList);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    @Override
    public DailyReportVo myCount() {
        //发送日报数
        long quantitySent = count(q -> q.eq(DailyReport::getCreateUser, SecurityUtils.getUserId()));
        long receivedQuantity = dailyReportDetailsService.count(q -> q.eq(DailyReportDetails::getRecipientId, SecurityUtils.getUserId()));
        IWrapper<DailyReport> wrapper = getWrapper();
        wrapper.eq(DailyReport::getCreateUser, SecurityUtils.getUserId());
        wrapper.eq("(date( create_time ) = curdate())", 1);
        long quantitySentToday = count(wrapper);
        DailyReportVo dailyReportVo = new DailyReportVo();
        dailyReportVo.setQuantitySent(quantitySent);
        dailyReportVo.setReceivedQuantity(receivedQuantity);
        dailyReportVo.setQuantitySentToday(quantitySentToday);
        return dailyReportVo;
    }

    @Override
    public void share(Long id, List<Long> toUserIdList) {
        String username = SecurityUtils.getUsername();
        Map<String, Object> msgMap = new HashMap<>();
        msgMap.put("businessId", id);
        msgMap.put("msg", String.format("%s给你分享了日报", username));
        for (Long toUserId : toUserIdList) {
            WebSocketServer.sendInfo(toUserId, 1, msgMap);
        }
    }

}
