package com.hzs.scm.sale.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.SaOrderFieldConstants;
import com.hzs.common.core.constant.SystemFieldConstants;
import com.hzs.common.core.constant.msg.DocumentMsgConstants;
import com.hzs.common.core.constant.msg.ScmMsgConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.core.utils.TransactionUtils;
import com.hzs.common.domain.sale.classify.BdSpecs;
import com.hzs.common.domain.sale.ext.SaDeliverExt;
import com.hzs.common.domain.sale.ext.SaDeliverItemsExt;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.common.domain.sale.ext.SaOrderItemsExt;
import com.hzs.common.domain.sale.order.SaOrder;
import com.hzs.common.domain.scm.pub.ScmItemSpecs;
import com.hzs.common.domain.scm.pub.ScmOrderApproveLog;
import com.hzs.common.domain.scm.sale.IcSaleoutB;
import com.hzs.common.domain.scm.sale.IcSaleoutH;
import com.hzs.common.domain.scm.sale.ext.IcSaleoutBExt;
import com.hzs.common.domain.scm.sale.ext.IcSaleoutHExt;
import com.hzs.common.domain.system.sys.SysUser;
import com.hzs.sale.order.ISaOrderItemsServiceApi;
import com.hzs.sale.order.ISaOrderServiceApi;
import com.hzs.sale.product.IProductServiceApi;
import com.hzs.scm.ic.service.IIcOnHandNumService;
import com.hzs.scm.no.service.IScmBillNoService;
import com.hzs.scm.pub.param.ScmApproveParam;
import com.hzs.scm.pub.service.IScmItemSpecsService;
import com.hzs.scm.pub.service.IScmOrderApproveLogService;
import com.hzs.scm.sale.mapper.IcSaleoutHMapper;
import com.hzs.scm.sale.param.SaleOutParam;
import com.hzs.scm.sale.service.IIcSaleoutBService;
import com.hzs.scm.sale.service.IIcSaleoutHService;
import com.hzs.system.sys.IUserServiceApi;
import com.hzs.system.sys.dto.ApprovalBusinessResultDTO;
import com.hzs.system.sys.dto.LoginUser;
import org.apache.dubbo.config.annotation.DubboReference;
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.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 销售出库单表头 服务实现类
 */
@Service
public class IcSaleoutHServiceImpl extends ServiceImpl<IcSaleoutHMapper, IcSaleoutH> implements IIcSaleoutHService {

    @Autowired
    private IScmBillNoService scmBillNoService;
    @Autowired
    private IIcSaleoutBService saleOutBiService;
    @Autowired
    private IIcOnHandNumService onHandNumService;
    @Autowired
    private IScmItemSpecsService scmItemSpecsService;
    @Autowired
    private IScmOrderApproveLogService scmOrderApproveLogService;
    @Autowired
    private IIcOnHandNumService icOnHandNumService;

    @DubboReference
    ISaOrderItemsServiceApi saOrderItemsServiceApi;
    @DubboReference
    ISaOrderServiceApi saOrderServiceApi;
    @DubboReference
    IProductServiceApi productServiceApi;
    @DubboReference
    IUserServiceApi userServiceApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSaleOutBySaDeliver(SaDeliverExt deliverExt) {
        // 根据发货单生成销售出库单
        if (deliverExt == null || CollectionUtil.isEmpty(deliverExt.getSaDeliverItemsExtList())) {
            return;
        }
        Long pkCreator = deliverExt.getPkCreator();
        SysUser sysUser = userServiceApi.selectUserById(pkCreator).getData();
        // 查询销售订单
        List<SaOrderExt> saOrderExtList = saOrderServiceApi.querySaOrderByDeliverList(deliverExt.getSaDeliverItemsExtList()).getData();
        if (CollectionUtil.isEmpty(saOrderExtList)) {
            throw new RuntimeException(ScmMsgConstants.SO_ORDER_NOT_EXIST);
        }
        Map<Long, SaOrderExt> saOrderExtMap = new HashMap<>();
        Map<Long, SaOrderItemsExt> saOrderItemsExtMap = new HashMap<>();
        for (SaOrderExt saOrderExt : saOrderExtList) {
            saOrderExtMap.put(saOrderExt.getPkId(), saOrderExt);
            for (SaOrderItemsExt saOrderItemsExt : saOrderExt.getOrderItemsExtList()) {
                saOrderItemsExtMap.put(saOrderItemsExt.getPkId(), saOrderItemsExt);
            }
        }
        // 查询规格
        List<Integer> querySpeceIdList = new ArrayList<>();
        for (SaDeliverItemsExt deliverItemsExt : deliverExt.getSaDeliverItemsExtList()) {
            String[] specsId = deliverItemsExt.getSpecsNameId().split(",");
            querySpeceIdList.addAll(Arrays.stream(specsId).map(Integer::valueOf).collect(Collectors.toList()));
        }
        List<BdSpecs> specsList = productServiceApi.queryBdSpecsByIdList(querySpeceIdList).getData();
        Map<Integer, BdSpecs> specsMap = specsList.stream().collect(Collectors.toMap(BdSpecs::getPkId, bdSpecs -> bdSpecs));
        Map<Long, IcSaleoutHExt> saleoutExtMap = new HashMap<>();
        for (SaDeliverItemsExt deliverItemsExt : deliverExt.getSaDeliverItemsExtList()) {
            // 根据订单获得仓库，公司
            if (saOrderExtMap.containsKey(deliverItemsExt.getPkOrder())) {
                // 销售订单
                SaOrderExt orderExt = saOrderExtMap.get(deliverItemsExt.getPkOrder());
                Long pkMember = orderExt.getPkMember();
                IcSaleoutHExt saleOutH;
                if (saleoutExtMap.containsKey(pkMember)) {
                    saleOutH = saleoutExtMap.get(pkMember);
                } else {
                    saleOutH = new IcSaleoutHExt();
                    saleOutH.setPkDept(sysUser.getPkDept().intValue());
                    saleOutH.setCustomerType(ESupplierType.MEMBER_CUSTOMER.getValue());
                    saleOutH.setPkCustomer(pkMember);
                    saleOutH.setPkWhsmanager(sysUser.getUserId());
                    saleOutH.setPkStorehouse(orderExt.getPkStorehouse());
                    saleOutH.setPkCorp(orderExt.getPkCorp());
                    saleOutH.setOrderDate(DateUtils.parseStringToDate(DateUtils.parseDateToFormat(DateUtils.YYYY_MM_DD, deliverExt.getDeliverTime())));
                    saleOutH.setOrderStatus(EScmOrderStatus.CLOSE.getValue());
                    saleOutH.setOrderCode(scmBillNoService.createScmBillNoByOrderType(EScmOrderType.SALE_OUT.getValue()));
                    saleOutH.setPrintStatus(EYesNo.NO.getIntValue());
                    saleOutH.setTotalNum(BigDecimal.ZERO);
                    saleOutH.setPkCreator(pkCreator);
                    saleOutH.setPkCountry(deliverExt.getPkCountry());
                    saleoutExtMap.put(pkMember, saleOutH);
                }
                IcSaleoutBExt saleOutB = new IcSaleoutBExt();
                if (saOrderItemsExtMap.containsKey(deliverItemsExt.getPkOrderItems())) {
                    SaOrderItemsExt orderItemsExt = saOrderItemsExtMap.get(deliverItemsExt.getPkOrderItems());
                    saleOutB.setPkUnit(orderItemsExt.getPkUnit());
                    saleOutB.setPkSaOrder(deliverItemsExt.getPkOrder());
                    saleOutB.setPkSaOrderItems(deliverItemsExt.getPkOrderItems());
                    saleOutB.setPkDelivery(deliverExt.getPkId());
                    saleOutB.setPkDeliverItems(deliverItemsExt.getPkId());
                    saleOutB.setPkProduct(deliverItemsExt.getPkProduct());
                    saleOutB.setBizDate(saleOutH.getOrderDate());
                    saleOutB.setPkStorehouse(orderExt.getPkStorehouse());
                    saleOutB.setPkRate(orderExt.getPkRate());
                    saleOutB.setNnum(BigDecimal.valueOf(deliverItemsExt.getQuantity()));
                    saleOutB.setNorigprice(orderItemsExt.getPrice());
                    saleOutB.setNtaxrate(BigDecimal.ZERO);
                    // 无税金额  = 无税单价*数量
                    saleOutB.setNorigmny(ComputeUtil.computeMultiply(saleOutB.getNorigprice(), saleOutB.getNnum()));
                    // 含税单价  = 无税单价*（1+税率）
                    saleOutB.setNorigtaxprice(ComputeUtil.computeMultiply(saleOutB.getNorigprice(),
                            ComputeUtil.computeAdd(BigDecimal.ONE, ComputeUtil.computeMultiply(saleOutB.getNtaxrate(), BigDecimal.valueOf(0.01)))));
                    // 税额 =无税单价*税率*数量
                    saleOutB.setNtax(ComputeUtil.computeMultiply(ComputeUtil.computeBonusMultiply(saleOutB.getNorigprice(), saleOutB.getNtaxrate()), saleOutB.getNnum()));
                    // 价税合计 含税单价*数量
                    saleOutB.setNorigtaxmny(ComputeUtil.computeMultiply(saleOutB.getNorigtaxprice(), saleOutB.getNnum()));
                    saleOutB.setIsGift(orderItemsExt.getIsGift());
                    saleOutB.setPkCreator(pkCreator);
                    saleOutB.setPkCountry(deliverExt.getPkCountry());
                    saleOutH.setTotalNum(ComputeUtil.computeAdd(saleOutH.getTotalNum(), saleOutB.getNnum()));
                    // 封装明细表
                    String[] specsIdArray = deliverItemsExt.getSpecsNameId().split(",");
                    List<Integer> speceIdList = Arrays.stream(specsIdArray).map(Integer::valueOf).collect(Collectors.toList());
                    List<ScmItemSpecs> scmItemSpecsList = new ArrayList<>();
                    for (Integer specsId : speceIdList) {
                        if (specsMap.containsKey(specsId)) {
                            BdSpecs bdSpecs = specsMap.get(specsId);
                            ScmItemSpecs scmItemSpecs = ScmItemSpecs.builder()
                                    .orderType(EScmOrderType.SALE_OUT.getValue())
                                    .pkSpecs(bdSpecs.getPkId())
                                    .pkSpecsType(bdSpecs.getPkSpecsType())
                                    .specsName(bdSpecs.getSpecsName())
                                    .build();
                            scmItemSpecs.setPkCreator(pkCreator);
                            scmItemSpecs.setPkCountry(deliverExt.getPkCountry());
                            scmItemSpecsList.add(scmItemSpecs);
                        }
                    }
                    saleOutB.setScmItemSpecsList(scmItemSpecsList);
                    if (saleOutH.getSaleoutbExtList() == null) {
                        List<IcSaleoutBExt> saleoutbList = new ArrayList<>();
                        saleoutbList.add(saleOutB);
                        saleOutH.setSaleoutbExtList(saleoutbList);
                    } else {
                        saleOutH.getSaleoutbExtList().add(saleOutB);
                    }
                }
            }
        }
        List<Long> saleOutIdList = baseMapper.querySaleOutSql(saleoutExtMap.size());
        int i = 0;
        for (Long pkMember : saleoutExtMap.keySet()) {
            IcSaleoutHExt icSaleOutExt = saleoutExtMap.get(pkMember);
            icSaleOutExt.setPkId(saleOutIdList.get(i));
            for (IcSaleoutBExt saleOutB : icSaleOutExt.getSaleoutbExtList()) {
                saleOutB.setPkSaleout(icSaleOutExt.getPkId());
            }
            i++;
        }
        List<IcSaleoutBExt> saleoutBiExtList = new ArrayList<>();
        List<IcSaleoutHExt> saleOutExtList = new ArrayList<>();
        saleoutExtMap.forEach((key, saleOutExt) -> {
            // 扣减库存
            saleOutExtList.add(saleOutExt);
            saleoutBiExtList.addAll(saleOutExt.getSaleoutbExtList());
        });
        List<Long> saleOutBiIdList = saleOutBiService.querySaleOutBiSql(saleoutBiExtList.size());
        for (int j = 0; j < saleoutBiExtList.size(); j++) {
            IcSaleoutBExt saleOutB = saleoutBiExtList.get(j);
            saleOutB.setPkId(saleOutBiIdList.get(j));
        }
        saleoutExtMap.forEach((key, saleOutExt) -> {
            // 扣减库存
            onHandNumService.mergeIcOnHandNumByGeneralOut(saleOutExt, EScmOrderType.SALE_OUT.getValue(), pkCreator);
        });

        // 保存销售出库
        baseMapper.insertSaleOutByList(saleOutExtList);
        // 保存销售出库明细
        saleOutBiService.insertSaleOutBiByList(saleoutBiExtList);
        // 保存销售出库规格
        saleOutExtList.forEach(saleOutExt -> {
            List<ScmItemSpecs> saveScmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(saleOutExt.getSaleoutbExtList(), saleOutExt.getPkId());
            if (saveScmItemSpecsList.size() > 0) {
                scmItemSpecsService.saveBatch(saveScmItemSpecsList);
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBackSaleOutByParam(IcSaleoutHExt saleOutExt, SaleOutParam saleOutParam) {
        // 复制
        IcSaleoutH icSaleoutH = BeanUtil.copyProperties(saleOutExt, IcSaleoutH.class);
        icSaleoutH.setReturnStatus(EYesNo.YES.getIntValue());
        icSaleoutH.setReturnReason(saleOutParam.getReturnReason());
        List<IcSaleoutB> saleoutBiList = BeanUtil.copyToList(saleOutExt.getSaleoutbExtList(), IcSaleoutB.class);
        Long pkSource = icSaleoutH.getPkId();
        icSaleoutH.setPkId(null);
        Date currentDate = DateUtils.currentDateTime();
        icSaleoutH.setOrderCode(scmBillNoService.createScmBillNoByOrderType(EScmOrderType.SALE_OUT.getValue()));
        icSaleoutH.setOrderStatus(EScmOrderStatus.SAVE.getValue());
        icSaleoutH.setOrderDate(currentDate);
        icSaleoutH.setCreationTime(currentDate);
        baseMapper.insert(icSaleoutH);
        for (IcSaleoutB saleOutB : saleoutBiList) {
            Long pkSourceB = saleOutB.getPkId();
            saleOutB.setPkSource(pkSource);
            saleOutB.setPkSourceB(pkSourceB);
            saleOutB.setPkId(null);
            saleOutB.setBizDate(currentDate);
            saleOutB.setCreationTime(currentDate);
            saleOutB.setTransType(ETransType.GENERAL_IN.getValue());
//            saleOutB.setNnum(saleOutB.getNnum().negate());
            saleOutB.setPkSaleout(icSaleoutH.getPkId());
            saleOutBiService.save(saleOutB);
        }
        List<ScmItemSpecs> saveScmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(saleoutBiList, icSaleoutH.getPkId());
        if (saveScmItemSpecsList.size() > 0) {
            scmItemSpecsService.saveBatch(saveScmItemSpecsList);
        }
    }

    @Override
    public List<IcSaleoutHExt> queryDisSaleOutExtCondition(SaleOutParam saleOutParam) {
        if (saleOutParam.getEndDate() != null) {
            saleOutParam.setEndDate(DateUtils.afterDate(1, ChronoUnit.DAYS, saleOutParam.getEndDate()));
        }
        return baseMapper.queryDisSaleOutExtCondition(saleOutParam);
    }

    @Override
    public IcSaleoutHExt querySaleOutExtById(SaleOutParam saleOutParam) {
        List<IcSaleoutHExt> saleOutExtList = baseMapper.queryDisSaleOutExtCondition(saleOutParam);
        if (saleOutExtList == null || saleOutExtList.size() == 0) {
            return null;
        }
        // 查询明细表，需要携带规格
        IcSaleoutHExt saleOutExt = saleOutExtList.get(0);
        List<IcSaleoutBExt> icSaleoutBiExtList = saleOutBiService.querySaleOutBiExtByPk(saleOutParam.getPkCountry(), saleOutExt.getPkId());
        saleOutExt.setSaleoutbExtList(icSaleoutBiExtList);
        return saleOutExt;
    }

    @Override
    public IcSaleoutHExt querySaleOutExtId(Long pkId, Integer orderStatus) {
        return baseMapper.querySaleOutExtId(pkId, orderStatus);
    }

    @Override
    public IcSaleoutHExt queryDisSaleOutExtById(Long pkId, Integer orderStatus) {
        SaleOutParam saleOutParam = new SaleOutParam();
        saleOutParam.setPkId(pkId);
        saleOutParam.setOrderStatus(orderStatus);
        List<IcSaleoutHExt> saleOutExtList = baseMapper.queryDisSaleOutExtCondition(saleOutParam);
        if (CollectionUtil.isNotEmpty(saleOutExtList)) {
            return saleOutExtList.get(0);
        }
        return null;
    }

    private void updateBackSaleOutStatus(Long pkId, LoginUser loginUser, Integer orderStatus) {
        UpdateWrapper<IcSaleoutH> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(SaOrderFieldConstants.ORDER_STATUS, orderStatus);
        updateWrapper.set(SystemFieldConstants.PK_MODIFIED, loginUser.getUserId());
        updateWrapper.set(SystemFieldConstants.MODIFIED_TIME, DateUtils.currentDateTime());
        updateWrapper.eq(SystemFieldConstants.PK_ID, pkId);
        update(updateWrapper);
    }

    private String approveBackSaleOutByStatus(ApprovalBusinessResultDTO approvalBusinessResultDTO, Integer scmOrderStatus, Integer approveStatus) {
        // 查询订单日志表
        List<ScmOrderApproveLog> scmOrderApproveLogList = scmOrderApproveLogService.queryScmOrderApproveLogByCondition(null, approvalBusinessResultDTO.getEApprovalBusiness().getValue(), approvalBusinessResultDTO.getBusinessCode());
        if (scmOrderApproveLogList == null || scmOrderApproveLogList.size() == 0) {
            return TransactionUtils.getContent(DocumentMsgConstants.DOCUMENT_NOT_EXISTS);
        }
        // 查询销售退货单
        ScmOrderApproveLog scmOrderApproveLog = scmOrderApproveLogList.get(0);
        IcSaleoutHExt saleOutExt = querySaleOutExtId(scmOrderApproveLog.getPkOrder(), EScmOrderStatus.SUBMIT.getValue());
        if (saleOutExt == null) {
            return TransactionUtils.getContent(DocumentMsgConstants.DOCUMENT_HAS_HANDLE);
        }
        // 查询销售出库单，状态为已完成
        for (IcSaleoutBExt saleOutBiExt : saleOutExt.getSaleoutbExtList()) {
            if (saleOutBiExt.getPkSource() == null) {
                return TransactionUtils.getContent(ScmMsgConstants.SALE_OUT_NOT_EXIST);
            }
            IcSaleoutHExt oldSaleOutExt = querySaleOutExtId(saleOutBiExt.getPkSource(), EScmOrderStatus.CLOSE.getValue());
            if (oldSaleOutExt == null) {
                return TransactionUtils.getContent(ScmMsgConstants.SALE_OUT_NOT_EXIST);
            }
        }
        // 更新采购入库单状态
        updateBackSaleOutStatus(saleOutExt.getPkId(), approvalBusinessResultDTO.getLoginUser(), scmOrderStatus);
        // 更新前程日志表状态
        scmOrderApproveLogService.updateScmOrderApproveStatus(scmOrderApproveLog.getPkId(), approvalBusinessResultDTO.getLoginUser().getUserId(), approveStatus);
        if (EAgentApprovalStatus.APPROVED.getValue() == approveStatus) {
            // 查询其他入库单明细表
            List<IcSaleoutBExt> saleOutBiExtList = saleOutBiService.queryBackSaleOutBiByPk(EScmOrderType.SALE_OUT.getValue(), saleOutExt.getSaleoutbExtList());
            if (saleOutBiExtList != null && saleOutBiExtList.size() > 0) {
                saleOutExt.setSaleoutbExtList(saleOutBiExtList);
            }
            // 退货入不良品仓
            // 根据销售订单查找对应的不良品仓
            // 查找销售订单
            for (IcSaleoutBExt saleOutBiExt : saleOutExt.getSaleoutbExtList()) {
                SaOrder saOrder = saOrderServiceApi.querySaOrderExtByPkId(saleOutBiExt.getPkSaOrder()).getData();
//                BdStorehouse bdStorehouse = currencyServiceApi.queryBdStorehouseByProvince(saOrder.getRecProvince(), 2).getData();
                if (saOrder.getPkStorehouse() == null) {
                    continue;
                }
                saleOutBiExt.setPkStorehouse(saOrder.getPkStorehouse());
            }
            // 更新现存量 // 更新采购订单累计入库数量
            icOnHandNumService.mergeIcOnHandNumByGeneralIn(saleOutExt, saleOutExt.getSaleoutbExtList(), EScmOrderType.SALE_OUT.getValue(), approvalBusinessResultDTO.getLoginUser().getUserId());
            // 回写原销售出库单，状态更新为已退货
            Set<Long> sourceIdSet = new HashSet<>();
            List<Long> orderItemsIdList = new ArrayList<>();
            for (IcSaleoutBExt saleOutBiExt : saleOutExt.getSaleoutbExtList()) {
                sourceIdSet.add(saleOutBiExt.getPkSource());
                orderItemsIdList.add(saleOutBiExt.getPkSaOrderItems());
            }
            for (Long aLong : sourceIdSet) {
                updateBackSaleOutStatus(aLong, approvalBusinessResultDTO.getLoginUser(), EScmOrderStatus.BACK.getValue());
            }
            // 回写销售订单
            if (!saOrderItemsServiceApi.orderItemsReturn(orderItemsIdList, approvalBusinessResultDTO.getLoginUser().getUserId(), saleOutExt.getPkCountry()).isSuccess()) {
                throw new RuntimeException("回写销售订单失败！");
            }
        }
        return null;
    }
}
