package com.bonus.material.clz.service.impl;

import com.bonus.common.biz.domain.ProjectTreeBuild;
import com.bonus.common.biz.domain.ProjectTreeNode;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.basic.domain.BmProject;
import com.bonus.material.clz.domain.vo.MaterialSltAgreementInfo;
import com.bonus.material.clz.domain.vo.sltAgreementInfo.MaterialSltInfoVo;
import com.bonus.material.clz.mapper.ClzSltAgreementInfoMapper;
import com.bonus.material.clz.service.ClzSltAgreementInfoService;
import com.bonus.material.common.domain.dto.SelectDto;
import com.bonus.material.common.domain.vo.AgreementVo;
import com.bonus.material.settlement.domain.SltAgreementReduce;
import com.bonus.material.settlement.domain.SltAgreementRelation;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author ma_sh
 * @create 2025/6/27 15:20
 */
@Service
public class ClzSltAgreementInfoServiceImpl implements ClzSltAgreementInfoService {

    @Resource
    private ClzSltAgreementInfoMapper clzSltAgreementInfoMapper;

    /**
     * 根据条件获取协议结算列表
     * @param bean 查询条件
     */
    @Override
    public List<MaterialSltAgreementInfo> getSltAgreementInfo4Project(MaterialSltAgreementInfo bean) {
        return clzSltAgreementInfoMapper.getSltAgreementInfo4Project(bean);
    }

    /**
     * 获取结算清单
     * @param info
     * @return
     */
    @Override
    public MaterialSltInfoVo getSltInfo(MaterialSltAgreementInfo info) {
        MaterialSltInfoVo sltInfoVo = new MaterialSltInfoVo();
        sltInfoVo.setUnitName(info.getUnitName());
        sltInfoVo.setProjectName(info.getProjectName());
        BigDecimal leaseCost = BigDecimal.valueOf(0.00);
        BigDecimal repairCost = BigDecimal.valueOf(0.00);
        BigDecimal scrapCost = BigDecimal.valueOf(0.00);
        BigDecimal loseCost = BigDecimal.valueOf(0.00);
        BigDecimal reducCost = BigDecimal.valueOf(0.00);
        //租赁费用列表
        List<MaterialSltAgreementInfo> leaseList = getLeaseList(info);
        //维修费用列表
        List<MaterialSltAgreementInfo> repairList = new ArrayList<>();
        //报废费用列表
        List<MaterialSltAgreementInfo> scrapList = new ArrayList<>();
        //丢失费用列表
        List<MaterialSltAgreementInfo> loseList = getLoseList(info);

        List<SltAgreementReduce> reductionList = getReductionList(info);
        sltInfoVo.setLeaseList(leaseList);
        sltInfoVo.setRepairList(repairList);
        sltInfoVo.setScrapList(scrapList);
        sltInfoVo.setLoseList(loseList);
        sltInfoVo.setReductionList(reductionList);
        for (MaterialSltAgreementInfo lease : leaseList) {
            if(lease.getCosts()!=null){
                leaseCost = leaseCost.add(lease.getCosts());
            }
        }
        for (MaterialSltAgreementInfo lose : loseList) {
            if(lose.getCosts()!=null){
                loseCost = loseCost.add(lose.getCosts());
            }
        }
        for (SltAgreementReduce reduction : reductionList) {
            if(reduction.getReduceLeaseMoney()!=null){
                reducCost = reducCost.add(reduction.getReduceLeaseMoney());
            }
        }
        sltInfoVo.setLeaseCost(leaseCost);
        sltInfoVo.setRepairCost(repairCost);
        sltInfoVo.setScrapCost(scrapCost);
        sltInfoVo.setLoseCost(loseCost);
        sltInfoVo.setReductionCost(reducCost);
        List<SltAgreementRelation> relations = getRelations(leaseList, repairList, scrapList, loseList, info);
        sltInfoVo.setRelations(relations);
        return sltInfoVo;
    }

    @Override
    public MaterialSltInfoVo mergerData(MaterialSltInfoVo vo, List<MaterialSltInfoVo> list, List<String> unitNames, List<String> projectNames) {
        vo.setUnitName(handleData(unitNames));
        vo.setProjectName(handleData(projectNames));
        BigDecimal leaseCost = BigDecimal.valueOf(0.00);
        BigDecimal repairCost = BigDecimal.valueOf(0.00);
        BigDecimal scrapCost = BigDecimal.valueOf(0.00);
        BigDecimal loseCost = BigDecimal.valueOf(0.00);
        BigDecimal reducCost = BigDecimal.valueOf(0.00);
        //租赁费用列表
        List<MaterialSltAgreementInfo> leaseList = new ArrayList<>();
        //维修费用列表
        List<MaterialSltAgreementInfo> repairList = new ArrayList<>();
        //报废费用列表
        List<MaterialSltAgreementInfo> scrapList = new ArrayList<>();
        //丢失费用列表
        List<MaterialSltAgreementInfo> loseList = new ArrayList<>();
        //减免费用列表
        List<SltAgreementReduce> reductionList = new ArrayList<>();
        List<SltAgreementRelation> relations = new ArrayList<>();
        for (MaterialSltInfoVo infoVo : list) {
            leaseCost = leaseCost.add(infoVo.getLeaseCost());
            repairCost = repairCost.add(infoVo.getRepairCost());
            scrapCost = scrapCost.add(infoVo.getScrapCost());
            loseCost = loseCost.add(infoVo.getLoseCost());
            reducCost = reducCost.add(infoVo.getReductionCost());
            leaseList.addAll(infoVo.getLeaseList());
            repairList.addAll(infoVo.getRepairList());
            scrapList.addAll(infoVo.getScrapList());
            loseList.addAll(infoVo.getLoseList());
            reductionList.addAll(infoVo.getReductionList());
            relations.addAll(infoVo.getRelations());
        }
        vo.setLeaseList(leaseList);
        vo.setRepairList(repairList);
        vo.setScrapList(scrapList);
        vo.setLoseList(loseList);
        vo.setReductionList(reductionList);
        vo.setLeaseCost(leaseCost);
        vo.setRepairCost(repairCost);
        vo.setScrapCost(scrapCost);
        vo.setLoseCost(loseCost);
        vo.setReductionCost(reducCost);
        vo.setRelations(relations);
        return vo;
    }

    @Override
    public String handleData(List<String> list) {
        StringBuilder sb = new StringBuilder();
        Set<String> set = new HashSet<>(list);
        for (String str : set) {
            sb.append(str).append("、");
        }
        return StringUtils.removeEnd(sb.toString(), "、");
    }

    /**
     * 工程下拉框
     *
     * @param bmProject 工程下拉框
     * @return 工程下拉框
     */
    @Override
    public AjaxResult getProjectListByUnitIds(BmProject bmProject) {
        List<ProjectTreeNode> groupList = new ArrayList<>();
        List<ProjectTreeNode> list = new ArrayList<>();
        try {
            if (bmProject.getUnitIds() != null) {
                Map<Integer,Integer> map= new HashMap<>();
                for (int i = 0; i < bmProject.getUnitIds().length; i++) {
                    int id = bmProject.getUnitIds()[i];
                    Integer[] projectIds= clzSltAgreementInfoMapper.getProjectListByUnitIds(bmProject.getUnitIds()[i]);
                    Map<Integer,Integer> mapTemp = new HashMap<>();
                    for (int projectId : projectIds) {
                        mapTemp.put(projectId, 1);
                    }
                    mapTemp.forEach((k,v) -> {
                        if (map.containsKey(k)) {
                            map.put(k, map.get(k) + v);
                        } else {
                            map.put(k, v);
                        }
                    });
                }
                if (!map.isEmpty()) {
                    List<Integer> keys = new ArrayList<>();
                    for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                        if (entry.getValue() == bmProject.getUnitIds().length) {
                            keys.add(entry.getKey());
                        }
                    }
                    for (Integer key : keys) {
                        List<ProjectTreeNode> listTemp = clzSltAgreementInfoMapper.getProjectList(key);
                        for (ProjectTreeNode node : listTemp) {
                            if (!list.contains(node)) {
                                list.add(node);
                            }
                        }
                    }
                }
            }

            if (CollectionUtils.isNotEmpty(list)) {
                // 创建树形结构（数据集合作为参数）
                ProjectTreeBuild treeBuild = new ProjectTreeBuild(list);
                // 原查询结果转换树形结构
                groupList = treeBuild.buildTree();
            }
        } catch (Exception e) {
            return AjaxResult.error(e+"工程下拉树查询失败");
        }
        return AjaxResult.success(groupList);
    }

    @Override
    public AjaxResult getAgreementInfoById(SelectDto dto) {
        List<AgreementVo> vo;
        try {
            List<AgreementVo> list = clzSltAgreementInfoMapper.getAgreementInfoById(dto.getUnitIds(), Integer.parseInt(dto.getProjectId()));
            if (CollectionUtils.isNotEmpty(list)) {
                vo = list;
            } else {
                return AjaxResult.error("未找到匹配的协议信息");
            }
        } catch (Exception e) {
            return AjaxResult.error(e+"协议查询失败");
        }
        return AjaxResult.success(vo);
    }

    /**
     * 提交结算清单
     * @param sltInfoVo
     * @return
     */
    @Override
    public int submitCosts(MaterialSltInfoVo sltInfoVo) {
        try {
            if (sltInfoVo.getAgreementIds() != null) {

                for (Long agreementId : sltInfoVo.getAgreementIds()) {
                    Long id = null;
                    sltInfoVo.setAgreementId(agreementId);
                    // 计算总成本
                    BigDecimal totalCost = BigDecimal.ZERO;
                    MaterialSltAgreementInfo info = new MaterialSltAgreementInfo();
                    info.setAgreementId(agreementId);

                    // 获取各项成本并累加
                    totalCost = totalCost.add(getLeaseList(info).stream()
                            .map(MaterialSltAgreementInfo::getCosts)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add));

                    /*totalCost = totalCost.add(getRepairList(info).stream()
                            .map(SltAgreementInfo::getCosts)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add));

                    totalCost = totalCost.add(getScrapList(info).stream()
                            .map(SltAgreementInfo::getCosts)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add));*/

                    totalCost = totalCost.add(getLoseList(info).stream()
                            .map(MaterialSltAgreementInfo::getCosts)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add));

                    totalCost = totalCost.subtract(getReductionList(info).stream()
                            .map(SltAgreementReduce::getLeaseMoney)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add));

                    // 设置总成本
                    sltInfoVo.setTotalCostAll(totalCost);
                    //查找是否驳回
                    int countReject = clzSltAgreementInfoMapper.getRejectCount(sltInfoVo);
                    if (countReject > 0) {
                        id = clzSltAgreementInfoMapper.getRejectId(sltInfoVo);
                        //修改
                        int countAgain = clzSltAgreementInfoMapper.updateRejectCount(sltInfoVo);
                        if (countAgain == 0) {
                            throw new ServiceException("slt_agreement_apply修改失败");
                        }
                        sltInfoVo.setUpdateTime(DateUtils.getNowDate());
                        sltInfoVo.setCreateBy(String.valueOf(SecurityUtils.getLoginUser().getUserid()));
                        /*int countTwo = clzSltAgreementInfoMapper.updateBmAgreementStatus(sltInfoVo);
                        if (countTwo != 1) {
                            throw new ServiceException("bm_agreement_info修改失败");
                        }*/
                    } else {
                        sltInfoVo.setCreateTime(DateUtils.getNowDate());
                        sltInfoVo.setCreateBy(String.valueOf(SecurityUtils.getLoginUser().getUserid()));
                        //新增
                        int countOne = clzSltAgreementInfoMapper.insertSltAgreementApply(sltInfoVo);
                        if (countOne != 1) {
                            throw new ServiceException("slt_agreement_apply新增失败");
                        }
                        // 插入成功后，sltInfoVo 的 id 属性将被自动设置为新生成的主键值
                        id = sltInfoVo.getId();
                        sltInfoVo.setUpdateTime(DateUtils.getNowDate());
                        /*int countTwo = clzSltAgreementInfoMapper.updateBmAgreementStatus(sltInfoVo);
                        if (countTwo != 1) {
                            throw new ServiceException("bm_agreement_info修改失败");
                        }*/
                    }
                    if (!sltInfoVo.getLeaseList().isEmpty()) {
                        List<MaterialSltAgreementInfo> filteredLeaseList = sltInfoVo.getLeaseList().stream()
                                .filter(lease -> lease.getAgreementId().equals(sltInfoVo.getAgreementId()))
                                .collect(Collectors.toList());
                        if (!filteredLeaseList.isEmpty()) {
                            clzSltAgreementInfoMapper.insertSltAgreementDetailLease(filteredLeaseList, id);
                        }
                    }
                    /*if (sltInfoVo.getRepairList().size() > 0) {
                        List<MaterialSltAgreementInfo> filteredRepairList = sltInfoVo.getRepairList().stream()
                                .filter(lease -> lease.getAgreementId().equals(sltInfoVo.getAgreementId()))
                                .collect(Collectors.toList());
                        if (!filteredRepairList.isEmpty()) {
                            clzSltAgreementInfoMapper.insertSltAgreementDetailRepair(filteredRepairList, id);
                        }
                    }
                    if (sltInfoVo.getScrapList().size() > 0) {
                        List<MaterialSltAgreementInfo> filteredScrapList = sltInfoVo.getScrapList().stream()
                                .filter(lease -> lease.getAgreementId().equals(sltInfoVo.getAgreementId()))
                                .collect(Collectors.toList());
                        if (!filteredScrapList.isEmpty()) {
                            clzSltAgreementInfoMapper.insertSltAgreementDetailScrap(filteredScrapList, id);
                        }
                    }*/
                    if (!sltInfoVo.getLoseList().isEmpty()) {
                        List<MaterialSltAgreementInfo> filteredLoseList = sltInfoVo.getLoseList().stream()
                                .filter(lease -> lease.getAgreementId().equals(sltInfoVo.getAgreementId()))
                                .collect(Collectors.toList());
                        if (!filteredLoseList.isEmpty()) {
                            clzSltAgreementInfoMapper.insertSltAgreementDetailLose(filteredLoseList, id);
                        }
                    }
                }
            }
            return 1;
        } catch (Exception e) {
            throw new ServiceException("错误信息描述");
        }
    }

    /**
     * 获取结算关系列表
     * @param leaseList 领料数据
     * @param repairList 维修数据
     * @param scrapList 报废数据
     * @param loseList 丢失数据
     * @param sltInfo 结算信息
     * @return 协议费用列表
     */
    private List<SltAgreementRelation> getRelations(List<MaterialSltAgreementInfo> leaseList, List<MaterialSltAgreementInfo> repairList, List<MaterialSltAgreementInfo> scrapList, List<MaterialSltAgreementInfo> loseList, MaterialSltAgreementInfo sltInfo) {
        List<SltAgreementRelation> relations = new ArrayList<>();
        SltAgreementRelation relation = new SltAgreementRelation();
        BigDecimal loseCost = BigDecimal.ZERO;
        BigDecimal leaseCost = BigDecimal.ZERO;
        BigDecimal scrapCost = BigDecimal.ZERO;
        BigDecimal repairCost = BigDecimal.ZERO;
        for (MaterialSltAgreementInfo lease : leaseList) {
            if (lease.getAgreementId().equals(sltInfo.getAgreementId())) {
                relation.setAgreementId(String.valueOf(lease.getAgreementId()));
                relation.setProjectName(lease.getProjectName());
                relation.setUnitName(lease.getUnitName());
                relation.setCompanyId(lease.getCompanyId());
                BigDecimal cost = lease.getCosts();
                leaseCost = leaseCost.add(cost);
            }
        }
        for (MaterialSltAgreementInfo repair : repairList) {
            if (repair.getAgreementId().equals(sltInfo.getAgreementId())) {
                BigDecimal cost = repair.getCosts();
                repairCost = repairCost.add(cost);
            }
        }
        for (MaterialSltAgreementInfo scrap : scrapList) {
            if (scrap.getAgreementId().equals(sltInfo.getAgreementId())) {
                BigDecimal cost = scrap.getCosts();
                scrapCost = scrapCost.add(cost);
            }
        }
        for (MaterialSltAgreementInfo lose : loseList) {
            if (lose.getAgreementId().equals(sltInfo.getAgreementId())) {
                //TODO 上面已经set过值，这里为什么还要set值
                relation.setAgreementId(String.valueOf(lose.getAgreementId()));
                relation.setProjectName(lose.getProjectName());
                relation.setUnitName(lose.getUnitName());
                relation.setCompanyId(lose.getCompanyId());
                BigDecimal cost = lose.getCosts();
                loseCost = loseCost.add(cost);
            }
        }
        relation.setLeaseCost(leaseCost);
        relation.setRepairCost(repairCost);
        relation.setScrapCost(scrapCost);
        relation.setLoseCost(loseCost);
        relations.add(relation);
        return relations;
    }

    /**
     * 获取减免费用列表
     * @param info 信息表
     */
    private List<SltAgreementReduce> getReductionList(MaterialSltAgreementInfo info) {
        SltAgreementReduce bean =new SltAgreementReduce();
        bean.setAgreementId(info.getAgreementId());
        return clzSltAgreementInfoMapper.getReductionList(bean);
    }

    /**
     * 获取丢失费用列表
     * @param info 信息表
     */
    private List<MaterialSltAgreementInfo> getLoseList(MaterialSltAgreementInfo info) {
        List<MaterialSltAgreementInfo> oneOfList = clzSltAgreementInfoMapper.getLoseList(info);
        List<MaterialSltAgreementInfo> loseList = new ArrayList<>(oneOfList);

        for (MaterialSltAgreementInfo bean : loseList) {
            if (Objects.isNull(bean.getBuyPrice())) {
                bean.setBuyPrice(BigDecimal.valueOf(0.00));
            }
            if (Objects.isNull(bean.getNum())) {
                bean.setNum(BigDecimal.valueOf(0L));
            }
            BigDecimal buyPrice = bean.getBuyPrice();
            BigDecimal num = bean.getNum();
            // 原价 x 数量
            BigDecimal costs = buyPrice.multiply(num);
            //计算租赁费用
            bean.setCosts(costs);
        }
        return loseList;
    }

    /**
     * 获取租赁费用列表
     * @param info 获取租赁费用列表参数
     */
    private List<MaterialSltAgreementInfo> getLeaseList(MaterialSltAgreementInfo info) {
        List<MaterialSltAgreementInfo> oneOfList = clzSltAgreementInfoMapper.getLeaseList(info);
        List<MaterialSltAgreementInfo> leaseList = new ArrayList<>(oneOfList);

        for (MaterialSltAgreementInfo bean : leaseList) {
            if (null == bean.getLeasePrice()) {
                bean.setLeasePrice(BigDecimal.valueOf(0.00));
            } else {
                bean.setLeasePrice(bean.getLeasePrice().setScale(2, RoundingMode.HALF_UP));
            }
            if (Objects.isNull(bean.getNum())) {
                bean.setNum(BigDecimal.valueOf(0L));
            }
            if (Objects.isNull(bean.getLeaseDays())) {
                bean.setLeaseDay(0L);
            }
            BigDecimal leasePrice = bean.getLeasePrice();
            BigDecimal num = bean.getNum();
            BigDecimal leaseDays = new BigDecimal(bean.getLeaseDays());
            BigDecimal costs = leasePrice.multiply(num).multiply(leaseDays).setScale(2, RoundingMode.HALF_UP);
            bean.setCosts(costs);
        }
        return leaseList;
    }
}
