package org.dromara.zjk.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dromara.common.core.constant.TenantConstants;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.RemoteDictService;
import org.dromara.system.api.model.RoleDTO;
import org.dromara.zjk.domain.*;
import org.dromara.zjk.domain.dto.CreditInfoDto;
import org.dromara.zjk.domain.dto.LeaveStsDto;
import org.dromara.zjk.domain.dto.PointInfoDto;
import org.dromara.zjk.domain.dto.SelExpertRuleDto;
import org.dromara.zjk.domain.vo.*;
import org.dromara.zjk.mapper.*;
import org.dromara.zjk.service.ZjkEvaluateService;
import org.dromara.zjk.utils.DateRangUtils;
import org.dromara.zjk.utils.NumberGenerator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author EDY
 * @description 针对表【zjk_evaluate(专家评价)】的数据库操作Service实现
 * @createDate 2024-11-01 10:11:52
 */
@Service
public class ZjkEvaluateServiceImpl extends ServiceImpl<ZjkEvaluateMapper, ZjkEvaluate>
    implements ZjkEvaluateService {
    @Resource
    private ZjkEvaluateMapper baseMapper;
    @Resource
    private ApplicationEventPublisher eventPublisher;
    @Resource
    private ZjkExpertMapper zjkExpertMapper;
    private RemoteDictService remoteDictService;
    @Resource
    private ZjkCreditRuleMapper zjkCreditRuleMapper;
    @Resource
    private ZjkProductMapper zjkProductMapper;
    @Resource
    private ZjkExpertMoneyConfigMapper zjkExpertMoneyConfigMapper;
    @Resource
    private ZjkExpertMoneyInfoMapper zjkExpertMoneyInfoMapper;
    @Resource
    private ZjkReviewPhaseMapper zjkReviewPhaseMapper;
    @Resource
    private ZjkPointMapper zjkPointMapper;

    @Override
    public TableDataInfo<ZjkEvaluateVO> getListToZj(ZjkEvaluateVO bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        //需要排除的用户id集合(包括当前登录userid)
        List<String> usersId = new ArrayList<>();
        //限定我参与的项目
        List<SelExpertRuleDto> rules = baseMapper.getMyJoinItems(userId);
        if (CollectionUtils.isEmpty(rules)) {
            return TableDataInfo.build();
        }
        List<String> ruleIds = rules.stream().map(SelExpertRuleDto::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(rules)) {
            rules.stream().forEach(item -> {
                List<String> hadEvaluatedUsers = baseMapper.getHadEvaluatedUsers(item.getItemId(), item.getReviewSn());
                usersId.addAll(hadEvaluatedUsers);
            });
        }
        usersId.add(String.valueOf(userId));
        List<String> exUserIds = usersId.stream().distinct().collect(Collectors.toList());
        bo.setUserId(String.valueOf(userId));
        IPage<ZjkEvaluateVO> result = baseMapper.getListToZj(pageQuery.build(), exUserIds, ruleIds, bo);
        result.getRecords().stream().forEach(item->{
            item.setXmEvaluateStatus(checkStatu(item));
        });
        //setTrans(result.getRecords());
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<ZjkEvaluateVO> getListToOrg(ZjkEvaluateVO bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
        // zjkEvaluate.setSourceRole();
        boolean isXmAdmin = StpUtil.hasRole(TenantConstants.XM_ROLE_KEY);
        if (isXmAdmin) {
            bo.setIsXmAdmin("1");
        }
        //需要排除的用户id集合(包括当前登录userid)
        List<String> usersId = new ArrayList<>();
        usersId.add(String.valueOf(userId));
        bo.setUserId(String.valueOf(userId));
        IPage<ZjkEvaluateVO> result = baseMapper.getListToOrg(pageQuery.build(), usersId, LoginHelper.getTenantId(), bo);
        return TableDataInfo.build(result);
    }

    @Override
    @Transactional
    public R<Void> addComment(ZjkEvaluateVO bo) {
        ZjkEvaluate zjkEvaluate = new ZjkEvaluate();
        BeanUtil.copyProperties(bo, zjkEvaluate);
        List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
        // zjkEvaluate.setSourceRole();

        if (!CollectionUtils.isEmpty(roles)) {
            List<String> rs = roles.stream().map(RoleDTO::getRoleKey).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(rs)) {
                if (rs.contains(UserConstants.ROLE_NAME_ZJ_KEY)) {
                    zjkEvaluate.setSourceRole(1);
                } else if (rs.contains(UserConstants.ROLE_NAME_ZJ_JG)) {
                    zjkEvaluate.setSourceRole(0);
                }
                if (rs.contains(TenantConstants.XM_ROLE_KEY)) {
                    zjkEvaluate.setSourceRole(2);
                }
            }
        }
        //专家角色，评价为未出席后，需更新其他评价也为未出席
        if (zjkEvaluate.getSourceRole() != null && zjkEvaluate.getSourceRole() == 2 && zjkEvaluate.getIsPresent().equals("0")) {
            List<String> evaIds = baseMapper.updateOtherInfoToUnPresent(zjkEvaluate);
            //更新对应积分
            if(!CollectionUtils.isEmpty(evaIds)){
                //清除未出席积分记录为0
               zjkPointMapper.clearUnPresentData(evaIds);
            }
        }

            baseMapper.insert(zjkEvaluate);
        //已出席，项目管理员评审专家后，需给财务打款记录表插入数据
        try {
            if (zjkEvaluate.getSourceRole() != null && zjkEvaluate.getSourceRole() == 2 && zjkEvaluate.getIsPresent().equals("1")) {
                ZjkExpert zjkExpert = zjkExpertMapper.selectById(zjkEvaluate.getEvaluateUser());
                if (zjkExpert != null) {
                    ZjkExpertMoneyInfo moneyInfo = new ZjkExpertMoneyInfo();
                    moneyInfo.setExpertId(bo.getEvaluateUser());
                    moneyInfo.setExpertName(zjkExpert.getExpertName());
                    moneyInfo.setExpertUnit(zjkExpert.getWorkUnit());
                    moneyInfo.setPaySn(NumberGenerator.generateUniqueNumber("fee",8));
                    moneyInfo.setAssignId(0);
                    moneyInfo.setProductType(zjkEvaluate.getItemStage()+"");
                    ZjkProduct zjkProduct = zjkProductMapper.selectById(zjkEvaluate.getItemId());
                    if (zjkExpert != null) {
                        moneyInfo.setProductId(zjkEvaluate.getItemId());
                        moneyInfo.setProductType(String.valueOf(zjkEvaluate.getItemStage()));
                        moneyInfo.setProductName(zjkProduct.getProductName());

                    }
                    try {
                        List<ZjkReviewPhaseVo> zjkReviewPhaseVos = zjkReviewPhaseMapper.selectUpdateZjkItemExpert(Long.parseLong(zjkEvaluate.getItemId()), zjkEvaluate.getItemStage() + "");
                        zjkReviewPhaseVos.stream().findFirst().ifPresent(zjkReviewPhaseVo -> moneyInfo.setReviewDate(zjkReviewPhaseVo.getReviewTime()));
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                    ZjkExpertMoneyConfig con = zjkExpertMoneyConfigMapper.selectById(zjkExpert.getPositionTitleLevel());
                    if (con != null) {
                        moneyInfo.setExpertMoney(con.getMoneyNumber());
                        moneyInfo.setExpertType(con.getMoneyType());
                        moneyInfo.setExpertTypeMoneyFee(con.getMoneyNumber());
                        moneyInfo.setExpertNoPayMoney(con.getMoneyNumber());
                    }
                    int insert = zjkExpertMoneyInfoMapper.insert(moneyInfo);
                    log.error("项目管理员评审专家后，给财务打款记录表插入数据：" + insert);

                }
            }
        } catch (Exception e) {
            log.error("项目管理员评审专家后，给财务打款记录表插入数据异常");
            e.printStackTrace();
        }

        //发布完成评价的积分事件
        QueryWrapper<ZjkExpert> wq = null;
        ZjkExpert zjkExpert = null;
        try {
            PointInfoDto pointInfoEvent = new PointInfoDto();
            pointInfoEvent.setEvaluateId(zjkEvaluate.getId());
            pointInfoEvent.setRuleKey(UserConstants.POINT_EVALUATE_KEY);
            pointInfoEvent.setExpertId(Long.valueOf(bo.getEvaluateUser()));
            pointInfoEvent.setPoints(bo.getBusLevelScore().add(bo.getWorkAttitudeScore()).add(bo.getRightApprovalScore()));
            wq = new QueryWrapper<>();
            wq.lambda().eq(ZjkExpert::getExpertId, bo.getEvaluateUser());
            zjkExpert = zjkExpertMapper.selectOne(wq);
            if (zjkExpert != null) {
                pointInfoEvent.setUserId(zjkExpert.getUserId());
            }
            eventPublisher.publishEvent(pointInfoEvent);
        } catch (Exception e) {
            log.error("发布完成评价的积分事件异常");
            e.printStackTrace();
        }
        //更新信用分
        //去过机构管理员 项目管理员 评价为缺席就扣减
        try {
            if (zjkEvaluate.getIsPresent().equals("0") && zjkEvaluate.getSourceRole()==2) {
                //发布完成评价的信用事件
                CreditInfoDto creditInfoDto = new CreditInfoDto();
                //获取信用规则
                LambdaQueryWrapper<ZjkCreditRule> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(ZjkCreditRule::getRuleKey, 3).last("Limit 1");
                ZjkCreditRuleVo zjkCreditRuleVo = zjkCreditRuleMapper.selectVoOne(lambdaQueryWrapper);
                creditInfoDto.setRuleKey(UserConstants.CREDIT_ABSENCE_KEY);
                creditInfoDto.setExpertId(Long.valueOf(bo.getEvaluateUser()));
                creditInfoDto.setCreditSum(zjkCreditRuleVo.getEachScore());
                wq.lambda().eq(ZjkExpert::getExpertId, bo.getEvaluateUser());
                if (zjkExpert != null) {
                    creditInfoDto.setUserId(zjkExpert.getUserId());
                }
                eventPublisher.publishEvent(creditInfoDto);
                //如果机构管理员评价为参评就增加
            } else {
                //发布完成评价的信用事件
                CreditInfoDto creditInfoDto = new CreditInfoDto();
                //获取信用规则
                LambdaQueryWrapper<ZjkCreditRule> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(ZjkCreditRule::getRuleKey, 1).last("Limit 1");
                ZjkCreditRuleVo zjkCreditRuleVo = zjkCreditRuleMapper.selectVoOne(lambdaQueryWrapper);
                creditInfoDto.setRuleKey(UserConstants.CREDIT_REVIEW_KEY);
                creditInfoDto.setExpertId(Long.valueOf(bo.getEvaluateUser()));
                creditInfoDto.setCreditSum(zjkCreditRuleVo.getEachScore());
                wq.lambda().eq(ZjkExpert::getExpertId, bo.getEvaluateUser());
                if (zjkExpert != null) {
                    creditInfoDto.setUserId(zjkExpert.getUserId());
                }
                eventPublisher.publishEvent(creditInfoDto);
            }
        } catch (Exception e) {
            log.error("发布完成评价的信用事件异常");
            e.printStackTrace();
        }
        return R.ok();
    }

    @Override
    public ZjkEvaluateVO getInfoById(String gid) {
        ZjkEvaluateVO zjkEvaluate = baseMapper.getInfoById(gid);
        return zjkEvaluate;
    }

    @Override
    public TableDataInfo<ZjkEvaluateVO> test() {
        System.out.println(baseMapper.testsysrole());
        return null;
    }

    @Override
    public TableDataInfo<ZjkEvaluateVO> getEvaluateListByExpert(ZjkEvaluateVO bo, PageQuery pageQuery) {
        IPage<ZjkEvaluateVO> result = baseMapper.getEvaluateListByExpert(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<ZjkEvaluateVO> getListToXm(ZjkEvaluateVO bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        //需要排除的用户id集合(包括当前登录userid)
        List<String> usersId = new ArrayList<>();
        //限定我参与的项目
        usersId.add(String.valueOf(userId));
        bo.setUserId(String.valueOf(userId));
        IPage<ZjkEvaluateVO> result = baseMapper.getListToXm(pageQuery.build(), usersId, null, bo);
        return TableDataInfo.build(result);
    }

    @Override
    public StsEvaluateNumVO getStsNum() {
        StsEvaluateNumVO res = baseMapper.getStsNum();
        return res;
    }

    @Override
    public R<StsEvaluateVO> getStsChart(Integer rangeMonth) {
        StsEvaluateVO res = new StsEvaluateVO();
        Date daysAgo = DateUtil.offsetDay(new Date(), -rangeMonth * 30 + 1);
        List<String> monthsRange = DateRangUtils.getMonthsRange(rangeMonth);
        //按月分组统计请假人数统计
        List<LeaveStsDto> numCs = baseMapper.getStsEvaluateNums(daysAgo, new Date());
        Map<Integer, Long> nm = numCs.stream().collect(Collectors.toMap(LeaveStsDto::getMt, LeaveStsDto::getCs));
        List<String> numSts = getYdataByMonth(nm, monthsRange);
        StsChartVO nums = StsChartVO.builder().xLine(monthsRange).yLine(numSts).build();
        res.setNumsSts(nums);
        //按月分组受评专家人数统计
        List<LeaveStsDto> perCs = baseMapper.getStsEvaluatePerNums(daysAgo, new Date());
        Map<Integer, Long> percsSts = perCs.stream().collect(Collectors.toMap(LeaveStsDto::getMt, LeaveStsDto::getCs));
        List<String> perSts = getYdataByMonth(percsSts, monthsRange);
        StsChartVO pers = StsChartVO.builder().xLine(monthsRange).yLine(perSts).build();
        res.setPersSts(pers);
        //评价细则五星率统计
        StsFiveStarVO build = null;
        List<StsFiveVO> stsFiveStar = baseMapper.getStsFiveStar();
        if (!CollectionUtils.isEmpty(stsFiveStar)) {
            build = StsFiveStarVO.builder().busLevelScore(stsFiveStar.get(0))
                .workAttitudeScore(stsFiveStar.get(1))
                .rightApprovalScore(stsFiveStar.get(2)).build();

        }
        res.setStarSts(build);
        return R.ok(res);
    }

    @Override
    public TableDataInfo<StsListVO> getStsList(ZjkEvaluateVO bo, PageQuery pageQuery) {
        if (pageQuery.getOrderByColumn() == null) {
            bo.setSortWay(1);
        }
        IPage<StsListVO> result = baseMapper.getStsList(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    @Override
    public List<StsListVO> selectStsEvaluateList(ZjkEvaluateVO bo) {
        bo.setSortWay(1);
        return baseMapper.getStsEvaluateList(bo);
    }


    public Integer checkStatu(ZjkEvaluateVO vo) {
      Integer status = baseMapper.checkIsPresentStatus(vo);
      if(status!=null && 0==status){
          //未出席
          return status;
        }else{
          return 1;

      }
    }

    private List<String> getYdataByMonth(Map<Integer, Long> data, List<String> monthsRange) {
        List<String> res = new ArrayList<>();
        if (data != null) {
            for (int i = 0; i < monthsRange.size(); i++) {
                String s = monthsRange.get(i).split("月")[0];
                res.add(String.valueOf(data.get(Integer.valueOf(s))));
            }
        }

        return res;
    }
}




