package com.hzs.scm.po.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.CacheConstants;
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.service.RedisService;
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.scm.po.PoOrder;
import com.hzs.common.domain.scm.po.PoOrderItems;
import com.hzs.common.domain.scm.po.ext.PoOrderExt;
import com.hzs.common.domain.scm.po.ext.PoOrderItemsExt;
import com.hzs.common.domain.scm.pub.ScmItemSpecs;
import com.hzs.common.domain.scm.pub.ScmOrderApproveLog;
import com.hzs.common.domain.scm.purchase.ext.IcPurchaseInBExt;
import com.hzs.common.domain.system.sys.SysUser;
import com.hzs.scm.no.service.IScmBillNoService;
import com.hzs.scm.po.mapper.PoOrderMapper;
import com.hzs.scm.po.param.PoOrderItemsParam;
import com.hzs.scm.po.param.PoOrderParam;
import com.hzs.scm.po.service.IPoOrderItemsService;
import com.hzs.scm.po.service.IPoOrderService;
import com.hzs.scm.pub.param.ItemSpecsParam;
import com.hzs.scm.pub.param.ScmApproveParam;
import com.hzs.scm.pub.service.IScmItemSpecsService;
import com.hzs.scm.pub.service.IScmOrderApproveLogService;
import com.hzs.system.base.ICurrencyServiceApi;
import com.hzs.system.base.dto.CurrencyDTO;
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.*;

/**
 * <p>
 * 采购订单表头 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2023-11-17
 */
@Service
public class PoOrderServiceImpl extends ServiceImpl<PoOrderMapper, PoOrder> implements IPoOrderService {


    @DubboReference
    private ICurrencyServiceApi currencyServiceApi;

    @DubboReference
    private IUserServiceApi userServiceApi;

    @Autowired
    private IScmBillNoService scmBillNoService;

    @Autowired
    private IPoOrderItemsService poOrderItemsService;

    @Autowired
    private IScmItemSpecsService scmItemSpecsService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IScmOrderApproveLogService scmOrderApproveLogService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertSavePoOrderByOrderParam(PoOrderParam poOrderParam, Long pkMember) {
        packagePoOrderByParam(poOrderParam, pkMember);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePorOrderByOrderParam(PoOrderExt poOrderExt, PoOrderParam poOrderParam, Long pkMember) {
        // 更新规格明细表，先删除在新增 根据主表主键删除
        scmItemSpecsService.deleteItemSpecsById(EScmOrderType.PO_ORDER.getValue(), poOrderExt.getPkId(), pkMember);
        poOrderExt.setPkCorp(poOrderParam.getPkCorp());
        poOrderExt.setPkCubasdoc(poOrderParam.getPkCubasdoc());
        poOrderExt.setOrderDate(poOrderParam.getOrderDate());
        poOrderExt.setContractCode(poOrderParam.getContractCode());
        poOrderExt.setRemark(poOrderParam.getRemark());
        // 更新订单明细表 分为3部分 删除的 新增的 修改的
        List<PoOrderItems> poOrderItemsList = getPoOrderItems(poOrderParam, pkMember, poOrderExt);
        // 重新处理订单明细，将订单明细分为 删除的、新增的、修改的
        List<PoOrderItemsExt> poOrderItemsExtList = poOrderExt.getPoOrderItemsExtList();
        // 剩余的就是需要删除的
        Map<Long, PoOrderItemsExt> poOrderItemsExtMap = new HashMap<>();
        poOrderItemsExtList.forEach(poOrderItemsExt ->
                poOrderItemsExtMap.put(poOrderItemsExt.getPkId(), poOrderItemsExt));
        List<PoOrderItems> insertOrderItems = new ArrayList<>();
        List<PoOrderItems> updateOrderItems = new ArrayList<>();
        List<ScmItemSpecs> saveScmItemSpecsList = new ArrayList<>();
        for (PoOrderItems poOrderItems : poOrderItemsList) {
            if (poOrderItems.getPkId() != null && poOrderItemsExtMap.containsKey(poOrderItems.getPkId())) {
                // 修改的
                poOrderItems.setPkCreator(poOrderItemsExtMap.get(poOrderItems.getPkId()).getPkCreator());
                updateOrderItems.add(poOrderItems);
                saveScmItemSpecsList.addAll(poOrderItems.getScmItemSpecsList());
                poOrderItemsExtMap.remove(poOrderItems.getPkId());
            } else {
                // 新增的
                poOrderItems.setPkOrder(poOrderExt.getPkId());
                insertOrderItems.add(poOrderItems);
            }
        }
        String purchaseLockKey = CacheConstants.IC_PURCHASE_IN_LOCK + poOrderExt.getPkId();
        try {
            if (!redisService.lockKeyOnce(purchaseLockKey)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            if (insertOrderItems.size() > 0) {
                // 保存订单明细 新增的
                poOrderItemsService.saveBatch(insertOrderItems);
                List<ScmItemSpecs> scmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(insertOrderItems, poOrderExt.getPkId());
                if (scmItemSpecsList.size() > 0) {
                    saveScmItemSpecsList.addAll(scmItemSpecsList);
                }
            }
            if (updateOrderItems.size() > 0) {
                // 修改订单明细 修改的
                updateOrderItems.forEach(updateItems ->
                        poOrderItemsService.updateById(updateItems));

            }
            if (poOrderItemsExtMap.size() > 0) {
                // 删除订单明细 删除的
                List<PoOrderItems> delOrderItems = new ArrayList<>();
                poOrderItemsExtMap.forEach((key, value) -> delOrderItems.add(value));
                poOrderItemsService.deleteOrderItemsService(delOrderItems, pkMember);
            }
            // 保存订单明细规格
            if (saveScmItemSpecsList.size() > 0) {
                scmItemSpecsService.saveBatch(saveScmItemSpecsList);
            }
            // 更新订单表
            updateById(poOrderExt);
        } finally {
            redisService.unlock(purchaseLockKey);
        }
    }

    @Override
    public PoOrderExt queryPoOrderById(Long pkOrder, Integer orderStatus) {
        return baseMapper.queryPoOrderById(pkOrder, orderStatus);
    }

    @Override
    public PoOrderExt queryDisPoOrderById(Long pkOrder, Integer orderStatus) {
        PoOrderParam poOrderParam = new PoOrderParam();
        poOrderParam.setPkId(pkOrder);
        poOrderParam.setOrderStatus(orderStatus);
        List<PoOrderExt> poOrderExtList = baseMapper.queryPoOrderByCondition(poOrderParam);
        if(CollectionUtil.isNotEmpty(poOrderExtList)){
            return poOrderExtList.get(0);
        }
        return null;
    }

    @Override
    public List<PoOrderExt> queryPoOrderByCondition(PoOrderParam poOrderParam) {
        if (poOrderParam.getEndDate() != null) {
            poOrderParam.setEndDate(DateUtils.afterDate(1, ChronoUnit.DAYS, poOrderParam.getEndDate()));
        }
        return baseMapper.queryPoOrderByCondition(poOrderParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePoOrder(Long pkOrder, Long pkMember) {
        String poOrderLockKey = CacheConstants.PO_ORDER_LOCK + pkOrder;
        if (!redisService.lockKeyOnce(poOrderLockKey)) {
            throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
        }
        // 删除规格明细表
        scmItemSpecsService.deleteItemSpecsById(EScmOrderType.PO_ORDER.getValue(), pkOrder, pkMember);
        // 删除订单明细表
        poOrderItemsService.deleteOrderItemsByPkOrder(pkOrder, pkMember);
        // 删除订单主表
        UpdateWrapper<PoOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(SystemFieldConstants.DEL_FLAG, EYesNo.NO.getIntValue());
        updateWrapper.set(SystemFieldConstants.PK_MODIFIED, pkMember);
        updateWrapper.set(SystemFieldConstants.MODIFIED_TIME, DateUtils.currentDateTime());
        updateWrapper.eq(SystemFieldConstants.PK_ID, pkOrder);
        update(updateWrapper);
        redisService.unlock(poOrderLockKey);
    }

    @Override
    public List<PoOrderExt> queryPoOrderByOrderItems(List<PoOrderItemsParam> orderItemsParamList) {
        return baseMapper.queryPoOrderByOrderItems(orderItemsParamList);
    }

    @Override
    public List<PoOrderExt> queryPoOrderToStoreByCondition(PoOrderParam poOrderParam) {
        //        if (CollectionUtil.isNotEmpty(poOrderExtList)) {
//            // 查询第一条的明细
//            poOrderExtList.get(0).setPoOrderItemsExtList(poOrderItemsService.queryPoOrderItemsByPk(poOrderParam.getPkCountry(), poOrderExtList.get(0).getPkId()));
//        }
        return baseMapper.queryPoOrderToStoreByCondition(poOrderParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePoOrderItemsTotalNum(List<IcPurchaseInBExt> icPurchaseInbList, Long pkMember) {
        // 更新订单明细累计入库数量
        poOrderItemsService.updatePoOrderItemsTotalNum(icPurchaseInbList, pkMember);
        // 更新订单主表
        baseMapper.updatePoOrderStatusByPurchase(icPurchaseInbList, pkMember, EScmOrderStatus.DELIVERY.getValue());
    }

    private String approvePoOrderByStatus(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);
        // 查询采购订单
        PoOrderExt poOrderExt = queryPoOrderById(scmOrderApproveLog.getPkOrder(), EScmOrderStatus.SUBMIT.getValue());
        if (poOrderExt == null) {
            log.error("订单撤单同意处理失败: 签呈已处理!");
            return TransactionUtils.getContent(DocumentMsgConstants.DOCUMENT_HAS_HANDLE);
        }
        // 更新采购入库单状态
        updatePoOrderStatus(poOrderExt.getPkId(), approvalBusinessResultDTO.getLoginUser(), scmOrderStatus);
        // 更新前程日志表状态
        scmOrderApproveLogService.updateScmOrderApproveStatus(scmOrderApproveLog.getPkId(), approvalBusinessResultDTO.getLoginUser().getUserId(), approveStatus);
        return null;
    }

    /*
     * @description: 将采购订单的参数转换为能保存的订单
     * @author: sui q
     * @date: 2023/11/20 15:53
     * @param: null null
     **/
    private void packagePoOrderByParam(PoOrderParam poOrderParam, Long pkMember) {
        PoOrder poOrder = BeanUtil.copyProperties(poOrderParam, PoOrder.class);
        List<PoOrderItems> poOrderItemsList = getPoOrderItems(poOrderParam, pkMember, poOrder);
        // 生成单据号
        poOrder.setOrderCode(scmBillNoService.createScmBillNoByOrderType(EScmOrderType.PO_ORDER.getValue()));
        // 保存主表
        save(poOrder);
        for (PoOrderItems poOrderItems : poOrderItemsList) {
            poOrderItems.setPkOrder(poOrder.getPkId());
        }
        // 保存子表
        poOrderItemsService.saveBatch(poOrderItemsList);
        List<ScmItemSpecs> saveScmItemSpecsList = scmItemSpecsService.packageOrderItemsSpecs(poOrderItemsList, poOrder.getPkId());
        if (saveScmItemSpecsList.size() > 0) {
            scmItemSpecsService.saveBatch(saveScmItemSpecsList);
        }
    }

    private List<PoOrderItems> getPoOrderItems(PoOrderParam poOrderParam, Long pkMember, PoOrder poOrder) {
        // 根据国家获得汇率
        CurrencyDTO currencyDTO = currencyServiceApi.getCurrency(poOrderParam.getPkCountry()).getData();
        poOrder.setPkRate(currencyDTO.getPkId());
        SysUser sysUser = userServiceApi.selectUserById(pkMember).getData();
        // 根据登录账号获得部门
        poOrder.setPkDept(sysUser.getPkDept().intValue());
        poOrder.setPkSalesman(pkMember);
        // 计算累计数量 累计价税合计
        // 总数量
        BigDecimal totalNum = BigDecimal.ZERO;
        // 价税合计
        BigDecimal totalOrigmny = BigDecimal.ZERO;
        List<PoOrderItems> poOrderItemsList = new ArrayList<>();
        Date date = DateUtils.currentDateTime();
        for (PoOrderItemsParam poOrderItemsParam : poOrderParam.getPoOrderItemsParamList()) {
            PoOrderItems poOrderItems = BeanUtil.copyProperties(poOrderItemsParam, PoOrderItems.class);
            if (EYesNo.YES.getIntValue() == poOrderItemsParam.getIsGift()) {
                poOrderItems.setNorigprice(BigDecimal.ZERO);
                poOrderItems.setNtaxrate(BigDecimal.ZERO);
                // 含税单价  = 无税单价*（1+税率）
                poOrderItems.setNorigtaxprice(BigDecimal.ZERO);
                // 无税金额  = 无税单价*数量
                poOrderItems.setNorigmny(BigDecimal.ZERO);
                // 税额 =无税单价*数量
                poOrderItems.setNtax(BigDecimal.ZERO);
                // 价税合计=含税单价*数量
                poOrderItems.setNorigtaxmny(BigDecimal.ZERO);
            } else {
                // 含税单价  = 无税单价*（1+税率）
                poOrderItems.setNorigtaxprice(ComputeUtil.computeMultiply(poOrderItems.getNorigprice(),
                        ComputeUtil.computeAdd(BigDecimal.ONE, ComputeUtil.computeMultiply(poOrderItems.getNtaxrate(), BigDecimal.valueOf(0.01)))));
                // 无税金额  = 无税单价*数量
                poOrderItems.setNorigmny(ComputeUtil.computeMultiply(poOrderItems.getNorigprice(), poOrderItems.getNnum()));
                // 税额 =无税单价*税率*数量
                poOrderItems.setNtax(ComputeUtil.computeMultiply(ComputeUtil.computeBonusMultiply(poOrderItems.getNorigprice(), poOrderItems.getNtaxrate()), poOrderItems.getNnum()));
                // 价税合计 含税单价*数量
                poOrderItems.setNorigtaxmny(ComputeUtil.computeMultiply(poOrderItems.getNorigtaxprice(), poOrderItems.getNnum()));
            }
            poOrderItems.setPkRate(currencyDTO.getPkId());
            totalNum = ComputeUtil.computeAdd(totalNum, poOrderItems.getNnum());
            totalOrigmny = ComputeUtil.computeAdd(totalOrigmny, poOrderItems.getNorigtaxmny());
            List<ItemSpecsParam> itemSpecsParamList = poOrderItemsParam.getScmItemSpecsList();
            scmItemSpecsService.packageScmItemByParam(itemSpecsParamList, poOrderItems, poOrderParam.getPkCountry(), pkMember,
                    poOrderParam.getPkId(), poOrderItems.getPkId(), EScmOrderType.PO_ORDER.getValue());
            poOrderItemsList.add(poOrderItems);
        }
        poOrder.setPkCountry(poOrderParam.getPkCountry());
        if (poOrderParam.getPkId() == null) {
            poOrder.setPkCreator(pkMember);
        } else {
            poOrder.setPkModified(pkMember);
            poOrder.setModifiedTime(date);
        }
        poOrder.setTotalNum(totalNum);
        poOrder.setTotalOrigmny(totalOrigmny);
        return poOrderItemsList;
    }

    private void updatePoOrderStatus(Long pkId, LoginUser loginUser, Integer orderStatus) {
        UpdateWrapper<PoOrder> 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);
    }

}
