package com.jeeplus.test.reimbursementAccountant.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.dto.UserDTO;
import com.jeeplus.sys.utils.DictUtils;
import com.jeeplus.sys.utils.StringUtils;
import com.jeeplus.sys.utils.UserUtils;
import com.jeeplus.test.reimbursementAccountant.domain.dto.AccountantReimbursementBusinessDTO;
import com.jeeplus.test.reimbursementAccountant.domain.dto.AccountantReimbursementBusinessReturnDTO;
import com.jeeplus.test.reimbursementAccountant.domain.dto.AccountantReimbursementDTO;
import com.jeeplus.test.reimbursementAccountant.domain.dto.AccountantReimbursementUserDTO;
import com.jeeplus.test.reimbursementAccountant.mapper.AccountantReimbursementBusinessMapper;
import com.jeeplus.test.reimbursementAccountant.mapper.AccountantReimbursementSysMapper;
import com.jeeplus.test.reimbursementAccountant.mapper.AccountantReimbursementUserMapper;
import com.jeeplus.test.reimbursementAccountant.service.AccountantReimbursementBusinessService;
import com.jeeplus.test.reimbursementsys.domain.dto.ReimbursementDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @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 AccountantReimbursementBusinessServiceImpl implements AccountantReimbursementBusinessService {

    @Autowired
    private AccountantReimbursementBusinessMapper mapper;
    @Autowired
    private AccountantReimbursementSysMapper reimbursementSysMapper;
    @Autowired
    private AccountantReimbursementUserMapper reimbursementUserMapper;


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

    @Override
    public AccountantReimbursementDTO getBusinessById(String id) {
        AccountantReimbursementDTO reimbursement = new AccountantReimbursementDTO();
        reimbursement.setBusinessCodeId(id);
        AccountantReimbursementBusinessDTO reimbursementBusiness = new AccountantReimbursementBusinessDTO();
        reimbursementBusiness.setBusinessCodeId(id);
        //根据业务id查询已收款的发票信息收款总额
        String getReceiptInvoiceByReimbursementId = reimbursementSysMapper.getReceiptInvoiceIncomeByReimbursementId(id);
        BigDecimal income = new BigDecimal(getReceiptInvoiceByReimbursementId);    //发票收入
        //根据业务id查询报销比例
        String getReimbursementRatioByReimbursementId = reimbursementSysMapper.getReimbursementRatioByReimbursementId(id);
        if(StringUtils.isBlank(getReimbursementRatioByReimbursementId)){
            getReimbursementRatioByReimbursementId = "0";
            reimbursement.setReimbursementRatio("0");
        }
        BigDecimal reimbursementRatio = new BigDecimal(getReimbursementRatioByReimbursementId);    //报销比例
        BigDecimal canReimbursementAmount = income.multiply(reimbursementRatio).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);    //该项目可报销额度计算
        //查询该业务总报销额度
        String alreadyReimbursementQuotaByBusinessCodeId = mapper.getAlreadyReimbursementQuotaByBusinessCodeId(reimbursementBusiness);
        BigDecimal allAlreadyReimbursementQuota = new BigDecimal(alreadyReimbursementQuotaByBusinessCodeId);    //总报销额度
        reimbursement.setAllAlreadyReimbursementQuota(allAlreadyReimbursementQuota.toString());
        reimbursement.setCanReimbursementAmount(canReimbursementAmount.toString());
        reimbursement.setSurplusReimbursementAmount(canReimbursementAmount.subtract(allAlreadyReimbursementQuota).toString());
        return reimbursement;
    }

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


    @Override
    public IPage<AccountantReimbursementUserDTO> findList(Page<AccountantReimbursementUserDTO> page, AccountantReimbursementUserDTO reimbursementUser) {
        return mapper.findList (page, reimbursementUser);
    }

    @Override
    public IPage<AccountantReimbursementUserDTO> getYearList(Page<AccountantReimbursementUserDTO> page, AccountantReimbursementUserDTO reimbursementUser) {
        IPage<AccountantReimbursementUserDTO> yearList = mapper.getYearList(page, reimbursementUser);
        List<AccountantReimbursementUserDTO> list = yearList.getRecords();
        if(list.size()>0){
            List<String> yearStrList = Lists.newArrayList();
            for (AccountantReimbursementUserDTO info : list) {
                yearStrList.add(info.getYear());
            }
            String years = StringUtils.join(yearStrList, ',');
            reimbursementUser.setYear(years);
            //根据人员和年份查询他的已报金额
            List<AccountantReimbursementUserDTO> reimbursementMoneyByYear = mapper.getReimbursementMoneyByYear(reimbursementUser);
            for (AccountantReimbursementUserDTO info : list) {
                for (AccountantReimbursementUserDTO yearInfo : reimbursementMoneyByYear) {
                    if(info.getYear().equals(yearInfo.getYear())){
                        //根据人员和年份查询报销人年度报销天数信息
                        AccountantReimbursementUserDTO reimbursementUserDTO = new AccountantReimbursementUserDTO();
                        reimbursementUserDTO.setUserId(reimbursementUser.getUserId());
                        reimbursementUserDTO.setYear(info.getYear());
                        AccountantReimbursementUserDTO userInfo = reimbursementUserMapper.queryByUserIdAndYear(reimbursementUserDTO);
                        if(null != userInfo.getReimbursementAllDay()){
                            //计算剩余天数
                            if(StringUtils.isBlank(yearInfo.getAlreadyReimbursementDay())){
                                yearInfo.setAlreadyReimbursementDay("0");
                            }
                            int surplusReimbursementDay = userInfo.getReimbursementAllDay() - Integer.parseInt(yearInfo.getAlreadyReimbursementDay());
                            info.setSurplusReimbursementDay(Integer.toString(surplusReimbursementDay));
                        }else{
                            info.setSurplusReimbursementDay("");
                        }
                        //获取当年总报销额度
                        BigDecimal allAlreadyReimbursementQuota = new BigDecimal(info.getReimbursementQuota());
                        //获取当年已报销额度
                        BigDecimal alreadyReimbursementQuota = new BigDecimal(yearInfo.getAlreadyReimbursementAmount());
                        info.setAlreadyReimbursementAmount(alreadyReimbursementQuota.toString());
                        //计算出当年所剩报销额度
                        info.setRemainReimbursementAmount(allAlreadyReimbursementQuota.subtract(alreadyReimbursementQuota).toString());
                        break;
                    }
                }
                //如果没有剩余报销天数 则将年报销天数添加到剩余报销天数中
                if(StringUtils.isBlank(info.getSurplusReimbursementDay())){
                    info.setSurplusReimbursementDay(info.getReimbursementAllDay().toString());
                }
            }

        }
        return yearList;
    }

    /**
     * 保存
     * @param reimbursementUser
     */
    @Override
    @Transactional(readOnly = false)
    public Map<String,Object> save(AccountantReimbursementBusinessDTO 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.getReimbursementType())){
            map.put("success", false);
            map.put("message", "请选择报销类型!");
            return map;
        }else{
            if("1".equals(reimbursementUser.getReimbursementType()) && (StringUtils.isBlank(reimbursementUser.getReimbursementDay()) || !StringUtils.isNumeric(reimbursementUser.getReimbursementDay()))){
                map.put("success", false);
                map.put("message", "报销天数不正确，请重新填写!");
                return map;
            }
        }
        if(StringUtils.isBlank(reimbursementUser.getReimbursementFsalary())){
            map.put("success", false);
            map.put("message", "报销类型不正确，请重新填写!");
            return map;
        }
        //根据人员id和报销年份查询该年度的报销信息
        AccountantReimbursementUserDTO reimbursementUserByUserIdAndYear = mapper.reimbursementUserByUserIdAndYear(reimbursementUser);
        if(null == reimbursementUserByUserIdAndYear){
            map.put("success", false);
            map.put("message", "该员工" + reimbursementUser.getYear() + "年度未添加报销信息，无法进行报销");
            return map;
        }
        //查询该人员该年度已报销额度(正常报销额度)
        String alreadyReimbursementQuota = mapper.getAlreadyReimbursementQuotaByUserIdAndYear(reimbursementUser);
        //判断本地报销额度是否超过该年度所剩余报销额度，如果超过，则不允许报销，并抛出。否则进行报销并保存报销数据
        BigDecimal alreadyReimbursementQuotaB = new BigDecimal(alreadyReimbursementQuota);    //已报销额度
        BigDecimal reimbursementAmount = null;
        if("1".equals(reimbursementUser.getReimbursementType())){
            BigDecimal reimbursementQuotaDay = new BigDecimal(reimbursementUser.getReimbursementQuotaDay());    //日报销额度
            BigDecimal reimbursementDay = new BigDecimal(reimbursementUser.getReimbursementDay());  //报销天数
            reimbursementAmount = reimbursementQuotaDay.multiply(reimbursementDay).setScale(2, BigDecimal.ROUND_HALF_UP);    //报销额度

            //往期加这次的总报销额度和当年的总报销额度进行比较，小于当年报销额度 则个人可以进行报销，否则，无法进行报销
            if(alreadyReimbursementQuotaB.add(reimbursementAmount).compareTo(new BigDecimal(reimbursementUser.getReimbursementQuota())) == 1){
                map.put("success", false);
                map.put("message", "本次报销金额已超出当年报销额度所剩余额，无法进行报销");
                return map;
            }
        }else{
            reimbursementAmount = new BigDecimal(reimbursementUser.getReimbursementAmount());
        }


        //根据业务id查询已收款的发票信息收款总额
        String getReceiptInvoiceByReimbursementId = reimbursementSysMapper.getReceiptInvoiceIncomeByReimbursementId(reimbursementUser.getBusinessCodeId());
        BigDecimal income = new BigDecimal(getReceiptInvoiceByReimbursementId);    //发票收入
        if(new BigDecimal("0").compareTo(income) == 0){
            map.put("success", false);
            map.put("message", "该业务可报销额度为0，无法进行报销");
            return map;
        }
        //根据业务id查询报销比例
        String getReimbursementRatioByReimbursementId = reimbursementSysMapper.getReimbursementRatioByReimbursementId(reimbursementUser.getBusinessCodeId());
        if(StringUtils.isBlank(getReimbursementRatioByReimbursementId)){
            map.put("success", false);
            map.put("message", "该业务报销比例为0，无法进行报销");
            return map;
        }
        BigDecimal reimbursementRatio = new BigDecimal(getReimbursementRatioByReimbursementId);    //报销比例
        BigDecimal canReimbursementAmount = income.multiply(reimbursementRatio).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);    //该项目可报销额度计算
        //查询该业务总报销额度
        String alreadyReimbursementQuotaByBusinessCodeId = mapper.getAlreadyReimbursementQuotaByBusinessCodeId(reimbursementUser);
        String gatheringStatus = mapper.getGatheringStatusById(reimbursementUser);
        BigDecimal allAlreadyReimbursementQuota = new BigDecimal(alreadyReimbursementQuotaByBusinessCodeId);    //总报销额度
        //往期加这次的总报销额度和当年的总报销额度进行比较，小于当年报销额度 则个人可以进行报销，否则，无法进行报销
        if(allAlreadyReimbursementQuota.add(reimbursementAmount).compareTo(canReimbursementAmount) == 1 && "1".equals(reimbursementUser.getReimbursementType())){
            map.put("success", false);
            map.put("message", "本次报销金额已超出该业务可报销额度所剩余额，无法进行报销");
            return map;
        } else if (allAlreadyReimbursementQuota.add(reimbursementAmount).compareTo(canReimbursementAmount) == 0 && "1".equals(gatheringStatus)){
            //如果报销额度和剩余报销额度相同
            AccountantReimbursementDTO reimbursementDTO = new AccountantReimbursementDTO();
            reimbursementDTO.setId(reimbursementUser.getBusinessCodeId());
            reimbursementDTO.setReimbursementStatus("1");

            mapper.updateReimbursementInfo(reimbursementDTO);
        }

        AccountantReimbursementDTO reimbursement = new AccountantReimbursementDTO();
        reimbursement.setBusinessCodeId(reimbursementUser.getBusinessCodeId());
        //根据该条发票信息查询同业务编号下的没有收款的发票信息
        List<AccountantReimbursementDTO> notGatheringTimeInvoice = reimbursementSysMapper.getNotGatheringTimeInvoiceBybusinessCodeId(reimbursement);
        if(notGatheringTimeInvoice.size() == 0){
            //查询该发票信息
            //如果所有的发票均已收款，则将业务信息添加全部收款状态
            reimbursementSysMapper.updateGatheringStatusById(reimbursementUser.getBusinessCodeId());
        }

        UserDTO user = UserUtils.get(reimbursementUser.getUserId());

        reimbursementUser.setReimbursementAmount(reimbursementAmount.toString());
        if(StringUtils.isNotBlank(reimbursementUser.getId())){
            reimbursementUser.preUpdate();
            //新增
            mapper.update(reimbursementUser);
        }else{
            reimbursementUser.preInsert();
            //新增
            mapper.save(reimbursementUser);
        }

        map.put("success", true);
        map.put("message", user.getName() + "报销" + reimbursementUser.getReimbursementAmount() + "金额成功");
        return map;
    }


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

    @Override
    @Transactional(readOnly = false)
    public void delete(List<String> idList) {
        //删除发票信息
        if(idList.size()>0){
            mapper.delete(idList);
        }
    }


    @Override
    public AccountantReimbursementBusinessReturnDTO findListByBusinessCodeId(AccountantReimbursementBusinessDTO reimbursementBusiness) {
        //查询报销批次信息
        AccountantReimbursementDTO reimbursementDTO = reimbursementSysMapper.queryBusinessById(reimbursementBusiness.getBusinessCodeId());

        List<AccountantReimbursementBusinessDTO> list = mapper.findListByBusinessCodeId(reimbursementBusiness);
        for (AccountantReimbursementBusinessDTO info : list) {
            info.setReimbursementType(DictUtils.getDictLabel(info.getReimbursementType(), "reimbursement_type", null));
            info.setReimbursementFsalary(DictUtils.getDictLabel(info.getReimbursementFsalary(), "reimbursement_fsalary", null));
            info.setOfficeType(DictUtils.getDictLabel(info.getOfficeType(), "reimbursement_office_type", null));
        }
        AccountantReimbursementBusinessReturnDTO reimbursementBusinessReturnDTO = new AccountantReimbursementBusinessReturnDTO();
        //获取业务报销信息
        AccountantReimbursementDTO business = this.getBusinessById(reimbursementBusiness.getBusinessCodeId());
        reimbursementBusinessReturnDTO.setList(list);
        //剩余报销额度
        reimbursementBusinessReturnDTO.setSurplusReimbursementAmount(business.getSurplusReimbursementAmount());
        //已报销额度
        reimbursementBusinessReturnDTO.setAlreadyReimbursementAmount(business.getAllAlreadyReimbursementQuota());
        //总报销额度
        reimbursementBusinessReturnDTO.setReimbursementQuota(business.getCanReimbursementAmount());
        reimbursementBusinessReturnDTO.setYear(reimbursementDTO.getYear());
        reimbursementBusinessReturnDTO.setBusinessCode(reimbursementDTO.getBusinessCode());
        return reimbursementBusinessReturnDTO;
    }

}
