package com.jwipc.finance.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jwipc.finance.entity.ReceiveVoucher;
import com.jwipc.finance.mapper.ReceiveVoucherMapper;
import com.jwipc.finance.model.po.ReceiveVoucherPO;
import com.jwipc.finance.model.po.StatementItemPO;
import com.jwipc.finance.model.po.StatisticVoucherPO;
import com.jwipc.finance.model.po.WriteOffVoucherCheckPO;
import com.jwipc.finance.model.query.ReceiveVoucherQuery;
import com.jwipc.finance.service.IReceiveVoucherService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.baomidou.dynamic.datasource.support.DdConstants.SLAVE;

/**
 * <p>
 * 对账模块-物料凭证 服务实现类
 * </p>
 *
 * @author shenyang.ou
 * @since 2024-03-04
 */
@Service
@DS(SLAVE)
public class ReceiveVoucherServiceImpl extends ServiceImpl<ReceiveVoucherMapper, ReceiveVoucher> implements IReceiveVoucherService {

    @Override
    public List<ReceiveVoucherPO> findPageByQuery(Page<ReceiveVoucher> dbPage, ReceiveVoucherQuery query) {
        if (dbPage==null){
            return baseMapper.findPageByQuery(query);
        }
        return baseMapper.findPageByQuery(dbPage,query);
    }

    /**
     * 获取开票申请中凭证数量及金额
     *
     * @param asId     需要排除的对账单ID
     * @param rvIdList 入库凭证ID
     * @return 结果
     */
    @Override
    public List<StatisticVoucherPO> findInvoicedApply(Long asId, List<Long> rvIdList) {
        return baseMapper.findInvoicedApply(asId,rvIdList);
    }

    /**
     * 获取对账单明细中凭证数量及金额
     *
     * @param asId      需要排除的对账单ID
     * @param asdIdList 需要排除的对账单明细ID
     * @param rvIdList  入库凭证ID
     * @return 结果
     */
    @Override
    public List<StatisticVoucherPO> findStatementDetail(Long asId, List<Long> asdIdList, List<Long> rvIdList) {
        return baseMapper.findStatementDetail(asId,asdIdList,rvIdList);
    }

    /**
     * 提供创建对账单时获取入库凭证数据
     *
     * @param query 查询条件
     * @return 结果
     */
    @Override
    public List<StatementItemPO> provideCreateStatement(ReceiveVoucherQuery query) {
        return baseMapper.provideCreateStatement(query);
    }

    @Override
    public List<StatementItemPO> provideCreatePaymentMatching(ReceiveVoucherQuery query) {
        return baseMapper.provideCreatePaymentMatching(query);
    }
    @Override
    public List<StatementItemPO> provideCreateCostMatching(ReceiveVoucherQuery query) {
        return baseMapper.provideCreateCostMatching(query);
    }

    @Override
    public List<StatementItemPO> provideDetailByPaymentMatchingId(Long paymentMatchingId) {
        return baseMapper.provideDetailByPaymentMatchingId(paymentMatchingId);
    }

    @Override
    public List<StatementItemPO> provideDetailByCostMatchingId(Long costMatchingId) {
        return baseMapper.provideDetailByCostMatchingId(costMatchingId);
    }

    @Override
    public List<StatementItemPO> queryMaterialDocReconciliationInfo(String factoryCode,List<String> cvKeyList) {
        return baseMapper.queryMaterialDocReconciliationInfo(factoryCode,cvKeyList);
    }

    @Override
    public List<StatementItemPO> provideCreateStatementPage(Page<ReceiveVoucher> dbPage, ReceiveVoucherQuery query) {
        if (dbPage==null){
            return baseMapper.provideCreateStatement(query);
        }
        return baseMapper.provideCreateStatement(dbPage,query);
    }

    /**
     * 处理凭证重冲销情况
     *
     * @param list 待检查数据
     * @return 结果
     */
    @Override
    public Map<Long, WriteOffVoucherCheckPO> handleWriteOffVoucherData(List<ReceiveVoucher> list) {
        BigDecimal ngeOne = new BigDecimal("-1");
        Map<Long, WriteOffVoucherCheckPO> result = Maps.newHashMap();

        final Map<String, List<ReceiveVoucher>> collect = list.stream().collect(Collectors.groupingBy(e -> e.getCvYear() + "#" + e.getCvCode() + "#" + e.getCvItemNo()));
        for (Map.Entry<String, List<ReceiveVoucher>> in : collect.entrySet()) {
            List<ReceiveVoucher> rvList = in.getValue();

            // 102(H)冲的是101(S); 123(S)冲的是122(H); 162(S)冲的是161(H)
            // 凭证之间相互抵消后剩余的数量; 被冲销的数量
            BigDecimal surplusNum = BigDecimal.ZERO, writeOffNum = BigDecimal.ZERO;
            // 可以编辑的入库凭证ID
            Long editRvId = 0L;
            // 冲销结果
            List<WriteOffVoucherCheckPO> dtoList = Lists.newArrayList();
            for (ReceiveVoucher rv : rvList) {
                if ("S".equals(rv.getVoucherFlag())) {
                    if ("101".equals(rv.getSapMoveType())) {
                        editRvId = rv.getId();
                        surplusNum = surplusNum.add(rv.getMvNum());
                    }
                    if ("123".equals(rv.getSapMoveType())) {
                        writeOffNum = writeOffNum.subtract(rv.getMvNum());
                        surplusNum = surplusNum.add(rv.getMvNum());
                    }
                    if ("162".equals(rv.getSapMoveType())) {
                        writeOffNum = writeOffNum.add(rv.getMvNum());
                        surplusNum = surplusNum.add(rv.getMvNum());
                    }
                }
                if ("H".equals(rv.getVoucherFlag())) {
                    if ("102".equals(rv.getSapMoveType())) {
                        writeOffNum = writeOffNum.add(rv.getMvNum());
                        surplusNum = surplusNum.add(rv.getMvNum().multiply(ngeOne));
                    }
                    if ("122".equals(rv.getSapMoveType())) {
                        writeOffNum = writeOffNum.add(rv.getMvNum());
                        surplusNum = surplusNum.add(rv.getMvNum().multiply(ngeOne));
                    }
                    if ("161".equals(rv.getSapMoveType())) {
                        editRvId = rv.getId();
                        surplusNum = surplusNum.add(rv.getMvNum().multiply(ngeOne));
                        writeOffNum = writeOffNum.add(rv.getMvNum().multiply(ngeOne));
                    }
                }

                WriteOffVoucherCheckPO dto = new WriteOffVoucherCheckPO();
                // 当凭证行不能编辑时, 设置凭证行最低对账数量应为0
                dto.setMinStatementQuantity(BigDecimal.ZERO);
                dto.setEditFlag(0);
                dto.setReceiveId(rv.getId());
                dtoList.add(dto);
            }

            // 不能保证冲销凭证全部冲销入库
            if (surplusNum.abs().compareTo(BigDecimal.ZERO) > 0) {
                for (WriteOffVoucherCheckPO dto : dtoList) {
                    if (dto.getReceiveId().equals(editRvId)) {
                        dto.setMinStatementQuantity(writeOffNum);
                        dto.setEditFlag(1);
                    }

                    result.put(dto.getReceiveId(), dto);
                }
            }

            // 一般冲销凭证都是冲销入库的全部
            if (surplusNum.abs().compareTo(BigDecimal.ZERO) == 0) {
                for (WriteOffVoucherCheckPO dto : dtoList) {
                    dto.setMinStatementQuantity(BigDecimal.ZERO);
                    dto.setEditFlag(0);
                    result.put(dto.getReceiveId(), dto);
                }
            }
        }

        return result;
    }

    /**
     * 根据参考凭证获取入库凭证数据
     *
     * @param supplierCode
     * @param cvKeyList    参考凭证数据组合(参考凭证年度#参考凭证号#参考凭证行号)
     * @param orderType
     * @return 结果
     */
    @Override
    public List<ReceiveVoucher> findByConsultVoucher(String supplierCode, List<String> cvKeyList, Integer orderType) {
        return baseMapper.findByConsultVoucher(supplierCode, cvKeyList, orderType);
    }

    @Override
    public ReceiveVoucher findByMvCode(String mvYear, String mvCode, String mvItemNo) {
        return baseMapper.findByMvCode(mvYear, mvCode, mvItemNo);
    }

    @Override
    public ReceiveVoucher findByMvCodeAndFactoryCode(String mvYear, String mvCode, String mvItemNo, String factoryCode) {
        return baseMapper.findByMvCodeAndFactoryCode(mvYear, mvCode, mvItemNo,factoryCode);
    }

    @Override
    public ReceiveVoucherPO findByErpSyncNo(String erpSyncNo) {
        return baseMapper.findByErpSyncNo(erpSyncNo);
    }

    @Override
    public List<ReceiveVoucherPO> findByPoAndAsNoNotNull(String poCode, String poItemNo,String factoryCode) {
        return baseMapper.findByPoAndAsNoNotNull(poCode,poItemNo,factoryCode);
    }

    @Override
    public List<ReceiveVoucherPO> findByPoAndItemNo(String poCode, String poItemNo,String factoryCode) {
        return baseMapper.findByPoAndItemNo(poCode,poItemNo,factoryCode);
    }

    @Override
    public List<ReceiveVoucherPO> getReturnVoucherData(String supplierCode, String factoryCode) {
        return baseMapper.getReturnVoucherData(supplierCode,factoryCode);
    }
    @Override
    public BigDecimal getPoReturnVoucherData(String supplierCode, String factoryCode,String companyCode) {
        return baseMapper.getPoReturnVoucherData(supplierCode,factoryCode,companyCode);
    }
}
