package com.mortals.xhx.module.check.service.impl;

import cn.hutool.core.date.DateUtil;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.IUser;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.util.DateUtils;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.base.system.message.MessageService;
import com.mortals.xhx.common.code.CheckStatusEnum;
import com.mortals.xhx.common.code.PerformTypeEnum;
import com.mortals.xhx.common.code.SubMethodEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.module.check.dao.CheckAttendRecordDao;
import com.mortals.xhx.module.check.model.CheckAttendRecordEntity;
import com.mortals.xhx.module.check.model.CheckComplainRecordEntity;
import com.mortals.xhx.module.check.model.vo.StaffCheckSummaryQuery;
import com.mortals.xhx.module.check.model.vo.StaffCheckSummaryVo;
import com.mortals.xhx.module.check.service.CheckAttendRecordService;
import com.mortals.xhx.module.dept.model.DeptEntity;
import com.mortals.xhx.module.dept.model.DeptPerformStatEntity;
import com.mortals.xhx.module.dept.model.DeptPerformStatQuery;
import com.mortals.xhx.module.dept.service.DeptPerformStatService;
import com.mortals.xhx.module.dept.service.DeptService;
import com.mortals.xhx.module.dingding.CheckDingMsg;
import com.mortals.xhx.module.dingding.personal.service.IDingPersonService;
import com.mortals.xhx.module.staff.model.*;
import com.mortals.xhx.module.staff.service.StaffPerformStatService;
import com.mortals.xhx.module.staff.service.StaffPerformSummaryService;
import com.mortals.xhx.module.staff.service.StaffService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * CheckAttendRecordService
 * 考勤绩效记录核查信息 service实现
 *
 * @author zxfei
 * @date 2023-07-10
 */
@Service("checkAttendRecordService")
@Slf4j
public class CheckAttendRecordServiceImpl extends AbstractCRUDServiceImpl<CheckAttendRecordDao, CheckAttendRecordEntity, Long> implements CheckAttendRecordService {

    @Autowired
    private StaffPerformSummaryService staffPerformSummaryService;
    @Autowired
    private IDingPersonService dingPersonService;
    @Autowired
    private StaffService staffService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private StaffPerformStatService staffPerformStatService;
    @Autowired
    private DeptPerformStatService deptPerformStatService;
    @Autowired
    private DeptService deptService;

    @Override
    protected void saveAfter(CheckAttendRecordEntity entity, Context context) throws AppException {
        //发送钉钉通知信息
        if (SubMethodEnum.系统自动.getValue() == entity.getSubMethod()) {
            sendCheckDingTalk(entity);
        }
        try {
            StaffCheckSummaryQuery query = new StaffCheckSummaryQuery();
            query.setStaffId(entity.getStaffId());
            query.setCheckTimeStart(DateUtils.getStrDate(entity.getCheckTime()));
            query.setCheckTimeEnd(query.getCheckTimeStart());
            summaryCheck(query);
        } catch (Exception e) {
            log.error("汇总已审核的核查记录出错", e);
        }
    }


    private void sendCheckDingTalk(CheckAttendRecordEntity entity) {
        String ruleStr = String.format("%s/%s/%s", PerformTypeEnum.考勤绩效.getDesc(), entity.getCategoryName(), entity.getRuleName());
        //绩效核查通知
        StaffEntity staffCache = staffService.getCache(entity.getStaffId().toString());
        if (!ObjectUtils.isEmpty(staffCache)) {
            Rest<String> personRest = dingPersonService.getPersonByMobile(staffCache.getPhoneNumber());
            if (YesNoEnum.YES.getValue() == personRest.getCode()) {
                CheckDingMsg checkDingMsg = new CheckDingMsg();
                checkDingMsg.setUserIds(personRest.getData());
                checkDingMsg.setDateTime(DateUtil.formatDateTime(entity.getErrorTime() == null ? new Date() : entity.getErrorTime()));
                checkDingMsg.setRuleStr(ruleStr);
                checkDingMsg.setPerformTypeStr(PerformTypeEnum.评价投诉绩效.getDesc());
                checkDingMsg.setScore(entity.getScore().toString());
                checkDingMsg.setSubAddType(entity.getSubAddType());
                checkDingMsg.setPath(String.format("#/api/v1/perform/info?id=%s&&performType=complain", entity.getId()));
                Rest<String> msgRest = messageService.sendDingTalkWorkMsg(checkDingMsg);
            } else {
                log.error("根据手机号码获取人员错误，msg:{}", personRest.getMsg());
            }
        } else {
            log.error("员工未找到,staffId:{}", entity.getStaffId());
        }
    }

    @Override
    public void examine(CheckAttendRecordEntity entity, Context context) throws AppException {
        if (entity.getId() == null) {
            throw new AppException("核查记录ID不能为空");
        }
        if (context != null && context.getUser() != null) {
            IUser user = context.getUser();
            entity.setUpdateUserId(user.getId());
            entity.setCheckPerson(user.getRealName());
        }
        entity.setCheckTime(new Date());
        entity.setUpdateTime(entity.getCheckTime());
        entity.setCheckStatus(CheckStatusEnum.已处理.getValue()); //处理状态(1.未处理,2.已处理)
        dao.update(entity);
        sendCheckDingTalk(entity);
        try {
            CheckAttendRecordEntity temp = this.get(entity.getId());
            if (temp != null) {
                StaffCheckSummaryQuery query = new StaffCheckSummaryQuery();
                query.setStaffId(temp.getStaffId());
                summaryCheck(query);
            }
        } catch (Exception e) {
            log.error("汇总已审核的核查记录出错", e);
        }
    }

    @Override
    public List<StaffCheckSummaryVo> summaryCheck(StaffCheckSummaryQuery query) throws AppException {
        if (StringUtils.isEmpty(query.getCheckTimeStart()) || StringUtils.isEmpty(query.getCheckTimeStart())) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            String startTime = format.format(calendar.getTime());
            calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
            String endTime = format.format(calendar.getTime());
            query.setCheckTimeStart(startTime);
            query.setCheckTimeEnd(endTime);
        }
        List<StaffCheckSummaryVo> summaryVoList = dao.summaryCheck(query);
        if (CollectionUtils.isNotEmpty(summaryVoList)) {
            for (StaffCheckSummaryVo vo : summaryVoList) {
                StaffPerformSummaryEntity staffPerformSummaryEntity = new StaffPerformSummaryEntity();
                staffPerformSummaryEntity.initAttrValue();
                BeanUtils.copyProperties(vo, staffPerformSummaryEntity, BeanUtil.getNullPropertyNames(vo));
                staffPerformSummaryEntity.setAttendScore(vo.getSumScore());
                StaffPerformSummaryQuery summaryQuery = new StaffPerformSummaryQuery();
                summaryQuery.setStaffId(vo.getStaffId());
                summaryQuery.setYear(vo.getYear());
                summaryQuery.setMonth(vo.getMonth());
                StaffPerformSummaryEntity temp = staffPerformSummaryService.selectOne(summaryQuery);
                if (temp != null) {
                    if (temp.getReviewScore() != null) {
                        staffPerformSummaryEntity.setReviewScore(temp.getReviewScore());
                    }
                    if (temp.getOtherScore() != null) {
                        staffPerformSummaryEntity.setOtherScore(temp.getOtherScore());
                    }
                    if (temp.getGoworkScore() != null) {
                        staffPerformSummaryEntity.setGoworkScore(temp.getGoworkScore());
                    }
                    if (temp.getEffectScore() != null) {
                        staffPerformSummaryEntity.setEffectScore(temp.getEffectScore());
                    }
                    if (temp.getComplainScore() != null) {
                        staffPerformSummaryEntity.setComplainScore(temp.getComplainScore());
                    }
                    BigDecimal erro = new BigDecimal(0);
                    erro = erro.add(staffPerformSummaryEntity.getReviewScore());
                    erro = erro.add(staffPerformSummaryEntity.getAttendScore());
                    erro = erro.add(staffPerformSummaryEntity.getOtherScore());
                    erro = erro.add(staffPerformSummaryEntity.getGoworkScore());
                    erro = erro.add(staffPerformSummaryEntity.getEffectScore());
                    erro = erro.add(staffPerformSummaryEntity.getComplainScore());
                    staffPerformSummaryEntity.setErrorScore(erro);
                    BigDecimal total = new BigDecimal(100);
                    staffPerformSummaryEntity.setTotalScore(total.subtract(erro));
                    staffPerformSummaryEntity.setId(temp.getId());
                    staffPerformSummaryEntity.setUpdateTime(new Date());
                    staffPerformSummaryService.update(staffPerformSummaryEntity);
                } else {
                    staffPerformSummaryEntity.setReviewScore(new BigDecimal(0));
                    staffPerformSummaryEntity.setOtherScore(new BigDecimal(0));
                    staffPerformSummaryEntity.setGoworkScore(new BigDecimal(0));
                    staffPerformSummaryEntity.setEffectScore(new BigDecimal(0));
                    staffPerformSummaryEntity.setErrorScore(vo.getSumScore());
                    BigDecimal total = new BigDecimal(100);
                    staffPerformSummaryEntity.setTotalScore(total.subtract(vo.getSumScore()));
                    staffPerformSummaryEntity.setCreateUserId(1l);
                    staffPerformSummaryEntity.setCreateTime(new Date());
                    staffPerformSummaryService.save(staffPerformSummaryEntity);
                }

            }
        }
        doSaveStaffPerformStat(query);
        doSaveDeptPerformStat(query);
        return summaryVoList;
    }

    @Override
    public void doSaveStaffPerformStat(StaffCheckSummaryQuery query) {
        if (StringUtils.isEmpty(query.getCheckTimeStart()) || StringUtils.isEmpty(query.getCheckTimeStart())) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            String startTime = format.format(calendar.getTime());
            calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
            String endTime = format.format(calendar.getTime());
            query.setCheckTimeStart(startTime);
            query.setCheckTimeEnd(endTime);
        }
        List<StaffPerformStatEntity> performStatList = dao.getStaffPerformStat(query);
        if(CollectionUtils.isNotEmpty(performStatList)){
            for(StaffPerformStatEntity entity:performStatList) {
                StaffPerformStatQuery tempQuery = new StaffPerformStatQuery();
                tempQuery.setStaffId(entity.getStaffId());
                tempQuery.setYear(entity.getYear());
                tempQuery.setMonth(entity.getMonth());
                tempQuery.setDay(entity.getDay());
                StaffPerformStatEntity temp = staffPerformStatService.selectOne(tempQuery);
                if (temp != null) {
                    StaffPerformStatEntity statEntity = new StaffPerformStatEntity();
                    statEntity.initAttrValue();
                    BeanUtils.copyProperties(temp, statEntity, BeanUtil.getNullPropertyNames(temp));
                    statEntity.setId(temp.getId());
                    statEntity.setUpdateTime(new Date());
                    statEntity.setAttendScoreAdd(entity.getAttendScoreAdd());
                    statEntity.setAttendScoreSub(entity.getAttendScoreSub());
                    computeStaff(statEntity);
                    staffPerformStatService.update(statEntity);
                }else {
                    StaffPerformStatEntity statEntity = new StaffPerformStatEntity();
                    statEntity.initAttrValue();
                    BeanUtils.copyProperties(entity, statEntity, BeanUtil.getNullPropertyNames(entity));
                    statEntity.setId(null);
                    computeStaff(statEntity);
                    statEntity.setCreateUserId(1l);
                    statEntity.setCreateTime(new Date());
                    staffPerformStatService.save(statEntity);
                }
            }
        }
    }

    @Override
    public void doSaveDeptPerformStat(StaffCheckSummaryQuery query) {
        if (StringUtils.isEmpty(query.getCheckTimeStart()) || StringUtils.isEmpty(query.getCheckTimeStart())) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            String startTime = format.format(calendar.getTime());
            calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
            String endTime = format.format(calendar.getTime());
            query.setCheckTimeStart(startTime);
            query.setCheckTimeEnd(endTime);
        }
        List<DeptPerformStatEntity> performStatList = dao.getDeptPerformStat(query);
        if(CollectionUtils.isNotEmpty(performStatList)){
            for(DeptPerformStatEntity entity:performStatList) {
                DeptPerformStatQuery tempQuery = new DeptPerformStatQuery();
                tempQuery.setDeptId(entity.getDeptId());
                tempQuery.setYear(entity.getYear());
                tempQuery.setMonth(entity.getMonth());
                tempQuery.setDay(entity.getDay());
                DeptPerformStatEntity temp = deptPerformStatService.selectOne(tempQuery);
                if (temp != null) {
                    DeptPerformStatEntity statEntity = new DeptPerformStatEntity();
                    statEntity.initAttrValue();
                    BeanUtils.copyProperties(temp, statEntity, BeanUtil.getNullPropertyNames(temp));
                    statEntity.setId(temp.getId());
                    statEntity.setUpdateTime(new Date());
                    statEntity.setAttendScoreAdd(entity.getAttendScoreAdd());
                    statEntity.setAttendScoreSub(entity.getAttendScoreSub());
                    computeDept(statEntity);
                    deptPerformStatService.update(statEntity);
                }else {
                    DeptPerformStatEntity statEntity = new DeptPerformStatEntity();
                    statEntity.initAttrValue();
                    BeanUtils.copyProperties(entity, statEntity, BeanUtil.getNullPropertyNames(entity));
                    statEntity.setId(null);
                    computeDept(statEntity);
                    statEntity.setCreateUserId(1l);
                    statEntity.setCreateTime(new Date());
                    deptPerformStatService.save(statEntity);
                }
            }
        }
    }

    private void computeStaff(StaffPerformStatEntity statEntity){
        BigDecimal totalAddScore = new BigDecimal(0);
        BigDecimal totalSubScore = new BigDecimal(0);
        BigDecimal totalScore = new BigDecimal(100);
        totalAddScore = totalAddScore.add(statEntity.getAttendScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getAttendScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getComplainScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getComplainScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getReviewScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getReviewScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getGoworkScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getGoworkScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getEffectScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getEffectScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getOtherScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getOtherScoreSub());
        statEntity.setTotalAddScore(totalAddScore);
        statEntity.setTotalSubScore(totalSubScore);
        totalScore = totalScore.add(totalAddScore);
        totalScore = totalScore.subtract(totalSubScore);
        statEntity.setTotalScore(totalScore);
    }

    private void computeDept(DeptPerformStatEntity statEntity){
        DeptEntity deptEntity = deptService.get(statEntity.getDeptId());
        BigDecimal totalAddScore = new BigDecimal(0);
        BigDecimal totalSubScore = new BigDecimal(0);
        BigDecimal totalScore = new BigDecimal(100);
        if(deptEntity!=null){
            totalScore = totalScore.multiply(new BigDecimal(deptEntity.getPersonNum()));
        }else {
            totalScore = totalScore.multiply(new BigDecimal(10));
        }
        totalAddScore = totalAddScore.add(statEntity.getAttendScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getAttendScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getComplainScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getComplainScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getReviewScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getReviewScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getGoworkScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getGoworkScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getEffectScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getEffectScoreSub());
        totalAddScore = totalAddScore.add(statEntity.getOtherScoreAdd());
        totalSubScore = totalSubScore.add(statEntity.getOtherScoreSub());
        statEntity.setTotalAddScore(totalAddScore);
        statEntity.setTotalSubScore(totalSubScore);
        totalScore = totalScore.add(totalAddScore);
        totalScore = totalScore.subtract(totalSubScore);
        statEntity.setTotalScore(totalScore);
    }
}