package com.jeeplus.test.reimbursementProject.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.jeeplus.sys.service.OfficeService;
import com.jeeplus.sys.service.UserService;
import com.jeeplus.sys.service.dto.OfficeDTO;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.sys.utils.DictUtils;
import com.jeeplus.sys.utils.StringUtils;
import com.jeeplus.sys.utils.UserUtils;
import com.jeeplus.test.reimbursementProject.domain.dto.ProjectReimbursementBusinessDTO;
import com.jeeplus.test.reimbursementProject.domain.dto.ProjectReimbursementBusinessReturnDTO;
import com.jeeplus.test.reimbursementProject.domain.dto.ProjectReimbursementUserDTO;
import com.jeeplus.test.reimbursementProject.mapper.ProjectReimbursementBusinessMapper;
import com.jeeplus.test.reimbursementProject.mapper.ProjectReimbursementUserMapper;
import com.jeeplus.test.reimbursementProject.service.ProjectReimbursementUserService;
import com.jeeplus.test.reimbursementsys.domain.dto.ReimbursementAddressDTO;
import com.jeeplus.test.reimbursementsys.domain.dto.ReimbursementBusinessDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;

/**
 * @author li-peike
 * @version 1.0.0
 * @ClassName ReimbursementSysServiceImpl.java
 * @Description TODO
 * @createTime 2022年05月06日 10:38:00
 */
@Service
@Transactional(readOnly = true)
public class ProjectReimbursementUserServiceImpl implements ProjectReimbursementUserService {

    @Autowired
    private ProjectReimbursementUserMapper mapper;

    @Autowired
    private ProjectReimbursementBusinessMapper businessMapper;

    @Autowired
    private OfficeService officeService;

    @Autowired
    private UserService userService;


    @Override
    public ProjectReimbursementUserDTO queryById(String id) {
        return mapper.queryById(id);
    }

    @Override
    public ProjectReimbursementUserDTO queryByUserIdAndYear(ProjectReimbursementUserDTO reimbursementUser) {
        return mapper.queryByUserIdAndYear(reimbursementUser);
    }


    @Override
    public IPage<ProjectReimbursementUserDTO> findList(Page<ProjectReimbursementUserDTO> page, ProjectReimbursementUserDTO reimbursementUser) {
        IPage<ProjectReimbursementUserDTO> pageList = mapper.findList(page, reimbursementUser);
        List<ProjectReimbursementUserDTO> list = pageList.getRecords();
        pageList.setRecords(list);
        return pageList;
    }

    /**
     * 保存
     * @param reimbursementUser
     */
    @Override
    @Transactional(readOnly = false)
    public Map<String,Object> save(ProjectReimbursementUserDTO reimbursementUser) {
        Map<String,Object> map = new HashMap<>();

        if(StringUtils.isBlank(reimbursementUser.getUserId())){
            map.put("success", false);
            map.put("message", "报销人员为空，无法进行添加报销信息!");
            return map;
        }
        if(StringUtils.isBlank(reimbursementUser.getYear())){
            map.put("success", false);
            map.put("message", "报销年份不正确，请重新填写!");
            return map;
        }

        if(StringUtils.isBlank(reimbursementUser.getReimbursementQuotaDay())){
            map.put("success", false);
            map.put("message", "日报销额度填写不正确!");
            return map;
        }
        if(null == reimbursementUser.getReimbursementAllDay()){
            map.put("success", false);
            map.put("message", "年可报销天数填写不正确!");
            return map;
        }
        //日报销额度
        BigDecimal reimbursementQuotaDay = new BigDecimal(reimbursementUser.getReimbursementQuotaDay());
        //年可报销天数
        BigDecimal reimbursementAllDay = new BigDecimal(reimbursementUser.getReimbursementAllDay());

        //计算并赋值年报销额度
        reimbursementUser.setReimbursementQuota(reimbursementQuotaDay.multiply(reimbursementAllDay).toString());

        UserDTO user = UserUtils.get(reimbursementUser.getUserId());
        if(StringUtils.isNotBlank(reimbursementUser.getId())){
            reimbursementUser.preUpdate();
            //新增
            mapper.update(reimbursementUser);
        }else{
            //查询该用户该年度是否已经添加报销额度
            ProjectReimbursementUserDTO queryByUserIdAndYear = mapper.queryByUserIdAndYear(reimbursementUser);
            if(null != queryByUserIdAndYear){
                map.put("success", false);
                map.put("message", user.getName() + " " + reimbursementUser.getYear() + "年度报销额度已添加，无法重复添加！");
                return map;
            }
            reimbursementUser.preInsert();
            //新增
            mapper.save(reimbursementUser);
        }

        map.put("success", true);
        map.put("message", user.getName() + " " + reimbursementUser.getYear() + "年度报销额度：" + reimbursementUser.getReimbursementQuota() +" 保存成功");
        return map;
    }


    @Override
    @Transactional(readOnly = false)
    public void update(ProjectReimbursementUserDTO reimbursementUser) {
        mapper.update(reimbursementUser);
    }

    @Override
    @Transactional(readOnly = false)
    public Map<String,Object> delete(List<String> idList) {
        Map<String, Object> map = new HashMap<>();
        if(idList.size()>0) {
            List<String> userName = Lists.newArrayList();
            //删除发票信息
            //判断该人员该年度是否已经存在报销情况，如存在则不可以删除
            //根据id集合查询人员信息
            for (String id : idList) {
                ProjectReimbursementUserDTO reimbursementUserDTO = mapper.queryById(id);
                ProjectReimbursementBusinessDTO reimbursementBusiness = new ProjectReimbursementBusinessDTO();
                reimbursementBusiness.setUserId(reimbursementUserDTO.getUserId());
                reimbursementBusiness.setYear(reimbursementUserDTO.getYear());
                List<ProjectReimbursementBusinessDTO> list = businessMapper.findListByUserIdAndYear(reimbursementBusiness);
                if (list.size() > 0) {
                    userName.add(reimbursementUserDTO.getUser().getName());
                }
            }
            if (userName.size() > 0) {
                map.put("success", false);
                String userNames = StringUtils.join(userName, "、");
                map.put("message", "员工 " + userNames + " 存在已报销情况，本次删除失败");
            } else {
                mapper.delete(idList);
                map.put("success", true);
                map.put("message", "删除成功");
            }
        }else{
            map.put("success", false);
            map.put("message", "没有需要删除的数据");
        }
        return map;
    }

    @Override
    public ProjectReimbursementBusinessReturnDTO findListByUserId(ProjectReimbursementUserDTO reimbursementUserDTO, ProjectReimbursementBusinessReturnDTO reimbursementBusinessReturn) {
        ProjectReimbursementBusinessDTO reimbursementBusiness = new ProjectReimbursementBusinessDTO();
        reimbursementBusiness.setUserId(reimbursementUserDTO.getUserId());
        reimbursementBusiness.setYear(reimbursementUserDTO.getYear());
        List<ProjectReimbursementBusinessDTO> list = businessMapper.findListByUserIdAndYear(reimbursementBusiness);

        reimbursementBusiness.setBeginDate(reimbursementBusinessReturn.getBeginDate());
        reimbursementBusiness.setEndDate(reimbursementBusinessReturn.getEndDate());
        reimbursementBusiness.setBeginReimbursementQuota(reimbursementBusinessReturn.getBeginReimbursementQuota());
        reimbursementBusiness.setEndReimbursementQuota(reimbursementBusinessReturn.getEndReimbursementQuota());
        reimbursementBusiness.setReimbursementAddress(reimbursementBusinessReturn.getReimbursementAddress());
        reimbursementBusiness.setReimbursementFsalary(reimbursementBusinessReturn.getReimbursementFsalary());
        reimbursementBusiness.setOfficeType(reimbursementBusinessReturn.getOfficeType());

        ProjectReimbursementBusinessReturnDTO reimbursementBusinessReturnDTO = new ProjectReimbursementBusinessReturnDTO();
        List<ProjectReimbursementBusinessDTO> showList = businessMapper.findListByUserIdAndYear(reimbursementBusiness);


        for (ProjectReimbursementBusinessDTO info : showList) {
            info.setReimbursementFsalary(DictUtils.getDictLabel(info.getReimbursementFsalary(), "reimbursement_fsalary", null));
            info.setOfficeType(DictUtils.getDictLabel(info.getOfficeType(), "reimbursement_office_type", null));
            if(StringUtils.isBlank(info.getReimbursementAddress())){
                info.setReimbursementAddress("—");
            }
        }

        //获取人员年度报销详情
        ProjectReimbursementUserDTO reimbursementUserInfo = mapper.queryByUserIdAndYear(reimbursementUserDTO);
        reimbursementBusinessReturnDTO.setList(showList);
        reimbursementBusinessReturnDTO.setUserName(reimbursementUserInfo.getUserName());
        reimbursementBusinessReturnDTO.setYear(reimbursementUserInfo.getYear());
        reimbursementBusinessReturnDTO.setReimbursementQuota(reimbursementUserInfo.getReimbursementQuota());

        //已报销额度
        BigDecimal alreadyReimbursementAmount = new BigDecimal("0");
        //已报销天数
        BigDecimal alreadyReimbursementDay = new BigDecimal("0");

        for (ProjectReimbursementBusinessDTO info : list) {
            BigDecimal bigDecimal = new BigDecimal(info.getReimbursementAmount());
            alreadyReimbursementAmount = alreadyReimbursementAmount.add(bigDecimal);
            if("1".equals(info.getReimbursementType())){
                alreadyReimbursementDay = alreadyReimbursementDay.add(new BigDecimal(info.getReimbursementDay()));
            }
            info.setReimbursementType(DictUtils.getDictLabel(info.getReimbursementType(), "reimbursement_type", null));
        }
        if(null != reimbursementBusinessReturn.getBeginDate() || null != reimbursementBusinessReturn.getEndDate() || StringUtils.isNotBlank(reimbursementBusinessReturn.getBeginReimbursementQuota()) || StringUtils.isNotBlank(reimbursementBusinessReturn.getEndReimbursementQuota())){
            for (ProjectReimbursementBusinessDTO info : showList) {
                info.setReimbursementType(DictUtils.getDictLabel(info.getReimbursementType(), "reimbursement_type", null));
            }
        }
        //剩余报销额度
        reimbursementBusinessReturnDTO.setSurplusReimbursementAmount(new BigDecimal(reimbursementBusinessReturnDTO.getReimbursementQuota()).subtract(alreadyReimbursementAmount).toString());
        //计算出可报销总天数
        BigDecimal reimbursementDay = new BigDecimal("0");
        if(null == reimbursementUserInfo.getReimbursementAllDay()){
            reimbursementDay = new BigDecimal(reimbursementBusinessReturnDTO.getReimbursementQuota()).divide(new BigDecimal(reimbursementUserInfo.getReimbursementQuotaDay()),2, BigDecimal.ROUND_HALF_UP);
        }else{
            reimbursementDay = new BigDecimal(reimbursementUserInfo.getReimbursementAllDay());
        }

        //剩余报销天数
        reimbursementBusinessReturnDTO.setSurplusReimbursementDay(reimbursementDay.subtract(alreadyReimbursementDay).toString());
        //报销天数
        reimbursementBusinessReturnDTO.setReimbursementDay(reimbursementDay.toString());
        //已报销天数
        reimbursementBusinessReturnDTO.setAlreadyReimbursementDay(alreadyReimbursementDay.toString());
        //已报销额度
        reimbursementBusinessReturnDTO.setAlreadyReimbursementAmount(alreadyReimbursementAmount.toString());
        //日报销额度
        reimbursementBusinessReturnDTO.setReimbursementQuotaDay(reimbursementUserInfo.getReimbursementQuotaDay());

        return reimbursementBusinessReturnDTO;
    }

    @Override
    public List<UserDTO> getUserByNameAndOfficeName(ProjectReimbursementUserDTO reimbursementUserDTO) {
        return mapper.getUserByNameAndOfficeName(reimbursementUserDTO);
    }

    @Override
    @Transactional(readOnly = false)
    public Map<String, Object> saveList(List<ProjectReimbursementUserDTO> reimbursementUserList) {

        List<ProjectReimbursementUserDTO> saveList = Lists.newArrayList();
        List<ProjectReimbursementUserDTO> existList = Lists.newArrayList();
        StringBuilder failureMsg = new StringBuilder ( );

        Map<String,Object> map = new HashMap<>();
        Map<String, List<ProjectReimbursementUserDTO>> stringListMap = dataDispose(reimbursementUserList);
        if(reimbursementUserList.size() != stringListMap.size()){
            map.put("success", false);
            map.put("message", "报销人员中存在重复项，无法进行导入!");
            return map;
        }


        for (ProjectReimbursementUserDTO reimbursementUser: reimbursementUserList) {
            if(StringUtils.isBlank(reimbursementUser.getYear())){
                map.put("success", false);
                map.put("message", reimbursementUser.getUserName() + " 的报销年份不正确，请重新填写!");
                return map;
            }
            if(StringUtils.isBlank(reimbursementUser.getReimbursementQuotaDay())){
                map.put("success", false);
                map.put("message", reimbursementUser.getUserName() + " 的日报销额度填写不正确!");
                return map;
            }
            if(null == reimbursementUser.getReimbursementAllDay()){
                map.put("success", false);
                map.put("message", reimbursementUser.getUserName() + " 的年可报销天数填写不正确!");
                return map;
            }
            //日报销额度
            BigDecimal reimbursementQuotaDay = new BigDecimal(reimbursementUser.getReimbursementQuotaDay());
            //年可报销天数
            BigDecimal reimbursementAllDay = new BigDecimal(reimbursementUser.getReimbursementAllDay());

            //计算并赋值年报销额度
            reimbursementUser.setReimbursementQuota(reimbursementQuotaDay.multiply(reimbursementAllDay).toString());

            //根据用户id和年份查询报数员工库表中是否存在数据
            //如果有，则将其从list列表中剔除
            ProjectReimbursementUserDTO reimbursementUserDTOS = mapper.queryByUserIdAndYear(reimbursementUser);
            if(null != reimbursementUserDTOS){
                existList.add(reimbursementUser);
            }else{
                reimbursementUser.preInsert();
                saveList.add(reimbursementUser);
            }

        }


        //新增
        if(saveList.size()>0){
            mapper.saveList(saveList);
        }

        if(existList.size()>0){
            for (ProjectReimbursementUserDTO user : existList) {
                failureMsg.append ( "。 " + user.getOfficeName() + " 部门下的员工 " + user.getUserName() + " 已添加，无法再次添加;" );
            }
        }

        map.put("success", true);
        map.put("saveCount", saveList.size());
        map.put("message", failureMsg);

        return map;
    }




    @Override
    @Transactional(readOnly = false)
    public Map<String, Object> initialize(String officeName,String officeType) {
        Map<String,Object> map = new HashMap<>();
        //根据部门名称  查询所属部门
        List<OfficeDTO> officeListByOfficeName = officeService.getOfficeAllByOfficeName(officeName);
        //如果不存在该部门，则进行抛出
        if(officeListByOfficeName.size() == 0){
            map.put("success", false);
            map.put("message", "未查询到部门信息。");
            return map;
        }
        //查询部门下所有有效人员信息
        List<String> officeIds = Lists.newArrayList();
        for (OfficeDTO office : officeListByOfficeName) {
            officeIds.add(office.getId());
        }
        List<UserDTO> officeUserList = userService.getUserByOfficeIds(officeIds);
        //根据部门人员查询数据库中已存在的人员信息
        if(officeUserList.size()>0){
            List<String> userIdList = Lists.newArrayList();
            for (UserDTO user : officeUserList) {
                userIdList.add(user.getId());
            }
            //获取当前年份
            Calendar date = Calendar.getInstance();
            String year = String.valueOf(date.get(Calendar.YEAR));

            //根据人员id集合和年份查询已存在的人员信息
            List<ProjectReimbursementUserDTO> existReimbursementUserList = mapper.getExistReimbursementUserList(userIdList, year,officeType);

            //排除已存在的人员信息
            for (ProjectReimbursementUserDTO existReimbursementUser: existReimbursementUserList) {
                Iterator iterator = officeUserList.iterator();
                while (iterator.hasNext()) {
                    UserDTO data = (UserDTO) iterator.next();
                    if (existReimbursementUser.getUserId().equals(data.getId())){
                        iterator.remove();
                        break;
                    }
                }
            }

            if(officeUserList.size()>0){
                //获取日报销额度
                String reimbursementQuotaDay = DictUtils.getDictLabel("1", "reimbursement_quota_day", null);
                //获取当年度的总天数
                int yearDay = LocalDate.now().lengthOfYear();
                //获取年度休假天数
                String holidayDay = DictUtils.getDictLabel("1", "reimbursement_holiday_day", null);
                Integer reimbursementAllDay = yearDay;
                if(StringUtils.isNotBlank(holidayDay)){
                    int i = Integer.parseInt(holidayDay);
                    reimbursementAllDay = yearDay - Integer.parseInt(holidayDay);
                }
                //日报销额度
                BigDecimal reimbursementQuotaDayB = new BigDecimal(reimbursementQuotaDay);
                //年可报销天数
                BigDecimal reimbursementAllDayB = new BigDecimal(reimbursementAllDay);
                //计算并赋值年报销额度
                BigDecimal reimbursementQuotaB = reimbursementQuotaDayB.multiply(reimbursementAllDayB);



                List<ProjectReimbursementUserDTO> userInfoList = Lists.newArrayList();

                //将不存在数据库中的人员信息进行批量添加
                for (UserDTO user : officeUserList) {
                    ProjectReimbursementUserDTO userInfo = new ProjectReimbursementUserDTO();
                    userInfo.setYear(year);
                    userInfo.setUserId(user.getId());
                    userInfo.setReimbursementQuotaDay(reimbursementQuotaDay);
                    userInfo.setReimbursementAllDay(reimbursementAllDay);
                    userInfo.setReimbursementQuota(reimbursementQuotaB.toString());
                    userInfo.setOfficeType(officeType);
                    userInfo.preInsert();
                    userInfoList.add(userInfo);
                }
                mapper.saveList(userInfoList);
            }
        }
        map.put("success", true);
        map.put("message", "人员初始化成功");

        return map;
    }


    /**
     * 文件数据分组
     * @param dataList
     * @return
     */
    public Map<String, List<ProjectReimbursementUserDTO>> dataDispose(List<ProjectReimbursementUserDTO> dataList) {
        Map<String, List<ProjectReimbursementUserDTO>> result = listMap(dataList);
        return result;
    }

    private Map<String, List<ProjectReimbursementUserDTO>> listMap(List<ProjectReimbursementUserDTO> list) {
        Map<String, List<ProjectReimbursementUserDTO>> userSignSerialMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(list)) {
            // 分组
            for (ProjectReimbursementUserDTO vo : list) {
                List<ProjectReimbursementUserDTO> tempList = userSignSerialMap.get(vo.getKeyFlag());
                /*如果取不到数据,那么直接new一个空的ArrayList**/
                if (tempList == null) {
                    tempList = new ArrayList<>();
                    tempList.add(vo);
                    userSignSerialMap.put(vo.getKeyFlag(), tempList);
                }
                else {
                    /*某个vo之前已经存放过了,则直接追加数据到原来的List里**/
                    tempList.add(vo);
                }
            }
        }
        return userSignSerialMap;
    }

}
