package com.gree.mall.manager.logic.material.manage;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.material.manage.WebsitPurchaseAdjustmentBean;
import com.gree.mall.manager.bean.material.manage.WebsitPurchaseAdjustmentVO;
import com.gree.mall.manager.commonmapper.MaterialMapper;
import com.gree.mall.manager.enums.material.MaterialFlagEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.logic.material.stock.WebitPurchaseStockLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.zfire.bean.ZfireParamBean;
import com.gree.mall.manager.zfire.util.FieldUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class WebsitPurchaseAdjustmentLogic {

    private final CommonLogic commonLogic;
    private final MaterialMapper materialMapper;
    private final WebsitPurchaseAdjustmentService websitPurchaseAdjustmentService;
    private final WebsitPurchaseAdjustmentItemService websitPurchaseAdjustmentItemService;
    private final WebsitPurchaseService websitPurchaseService;
    private final WebsitPurchaseItemService websitPurchaseItemService;
    private final WebsitGoodsService websitGoodsService;
    private final WebitPurchaseStockLogic webitPurchaseStockLogic;

    public IPage<WebsitPurchaseAdjustmentVO> page(ZfireParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.materialParam(zfireParamBean, WebsitPurchaseAdjustmentVO.class, adminUser);

        return materialMapper.websitPurchaseAdjustmentPage(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
    }

    public WebsitPurchaseAdjustmentBean detail(String purchaseAdjustmentId) {
        final WebsitPurchaseAdjustment adjustment = websitPurchaseAdjustmentService.getById(purchaseAdjustmentId);
        WebsitPurchaseAdjustmentBean bean = new WebsitPurchaseAdjustmentBean();
        BeanUtils.copyProperties(adjustment, bean);
        final List<WebsitPurchaseAdjustmentItem> items = websitPurchaseAdjustmentItemService.lambdaQuery()
                .eq(WebsitPurchaseAdjustmentItem::getPurchaseAdjustmentId, purchaseAdjustmentId)
                .list();
        bean.setItems(items);
        return bean;
    }

    @Transactional
    public WebsitPurchaseAdjustmentBean add(WebsitPurchaseAdjustmentBean bean) {
        WebsitPurchaseAdjustment existObj = websitPurchaseAdjustmentService.lambdaQuery()
                .eq(WebsitPurchaseAdjustment::getRef, bean.getRef())
                .lt(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.OK.getKey())
                .one();

        if (Objects.nonNull(existObj)) {
            throw new RemoteServiceException("发现一张未审核采购调整单单号为：" + existObj.getPurchaseAdjustmentId() + "，请先处理！");
        }

        // 获取采购订单信息
        getPurchaseInfo(bean);

        // 保存采购调整单
        bean.insert();
        // 保存采购调整单明细
        websitPurchaseAdjustmentItemService.saveBatch(bean.getItems());

        return bean;
    }

    private void getPurchaseInfo(WebsitPurchaseAdjustmentBean bean) throws RemoteServiceException {
        bean.setPurchaseAdjustmentId(IdWorker.getIdStr());
        // 获取采购订单信息
        WebsitPurchase purchase = websitPurchaseService.lambdaQuery()
                .eq(WebsitPurchase::getPurchaseId, bean.getRef())
                .eq(WebsitPurchase::getWebsitId, bean.getWebsitId())
                .eq(WebsitPurchase::getFlag, MaterialFlagEnum.OK.getKey())
                .one();
;

        if (Objects.isNull(purchase)) {
            throw new RemoteServiceException("找不到对应的采购订单：" + bean.getRef());
        }

        bean.setCompanyWechatId(purchase.getCompanyWechatId())
                .setCompanyWechatName(purchase.getCompanyWechatName());
        bean.setFlag(MaterialFlagEnum.SAVE.getKey());
        bean.setPurchaseTime(purchase.getPurchaseTime());
        bean.setStorageId(purchase.getStorageId());
        bean.setStorageName(purchase.getStorageName());

        // 获取采购订单明细信息
        List<WebsitPurchaseItem> purchaseItemList = websitPurchaseItemService.lambdaQuery()
                .eq(WebsitPurchaseItem::getPurchaseId, purchase.getPurchaseId())
                .list();

        List<WebsitPurchaseAdjustmentItem> adjustmentBeanItems = new ArrayList<>();

        for (WebsitPurchaseItem item : purchaseItemList) {
            WebsitPurchaseAdjustmentItem purchaseAdjustmentItem = new WebsitPurchaseAdjustmentItem();
            purchaseAdjustmentItem.setPurchaseAdjustmentId(bean.getPurchaseAdjustmentId());
            purchaseAdjustmentItem.setGoodsId(item.getGoodsId());
            purchaseAdjustmentItem.setGoodsName(item.getGoodsName());
            purchaseAdjustmentItem.setCost(item.getCost());
            purchaseAdjustmentItem.setRecQty(item.getRecQty());
            purchaseAdjustmentItem.setRecGiftQty(item.getRecGiftQty());
            purchaseAdjustmentItem.setInStockCost(item.getInStockCost());
            purchaseAdjustmentItem.setInStockQty(item.getInStockQty());
            purchaseAdjustmentItem.setAdjustCost(item.getCost());
            purchaseAdjustmentItem.setAdjustQty(item.getRecQty());
            purchaseAdjustmentItem.setAdjustGiftQty(item.getRecGiftQty());
            purchaseAdjustmentItem.setAdjustInStockCost(item.getInStockCost());
            purchaseAdjustmentItem.setAdjustInStockQty(item.getInStockQty());
            purchaseAdjustmentItem.setGoodsStockUnit(item.getGoodsStockUnit());
            purchaseAdjustmentItem.setGoodsSpecification(item.getGoodsSpecification());
            adjustmentBeanItems.add(purchaseAdjustmentItem);
        }

        bean.setItems(adjustmentBeanItems);
    }

    @Transactional
    public void update(WebsitPurchaseAdjustmentBean purchaseAdjustmentBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        // 检查明细
        this.validPurchaseItem(purchaseAdjustmentBean);
        // 校验商品进价倍率并转换入库数量
        this.validGoodsCost(purchaseAdjustmentBean);
        // 更新主表
        websitPurchaseAdjustmentService.lambdaUpdate()
                .eq(WebsitPurchaseAdjustment::getPurchaseAdjustmentId, purchaseAdjustmentBean.getPurchaseAdjustmentId())
                .eq(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.SAVE.getKey())
                .set(WebsitPurchaseAdjustment::getUpdateBy, adminUser.getNickName())
                .set(WebsitPurchaseAdjustment::getUpdateTime, DateUtil.date())
                .set(WebsitPurchaseAdjustment::getRemark, purchaseAdjustmentBean.getRemark())
                .set(StringUtils.isNotBlank(purchaseAdjustmentBean.getStorageId()), WebsitPurchaseAdjustment::getStorageId, purchaseAdjustmentBean.getStorageId())
                .set(StringUtils.isNotBlank(purchaseAdjustmentBean.getStorageName()), WebsitPurchaseAdjustment::getStorageName, purchaseAdjustmentBean.getStorageName())
                .update();
        // 更新明细
        websitPurchaseAdjustmentItemService.updateBatchById(purchaseAdjustmentBean.getItems());
    }

    private void validPurchaseItem(WebsitPurchaseAdjustmentBean purchaseAdjustmentBean) throws RemoteServiceException {
        // 过滤校验调整进价、调整数量少于等于0，调整增品数量少于0的明细
        BigDecimal zeroVal = new BigDecimal("0");
        List<WebsitPurchaseAdjustmentItem> existFilter = purchaseAdjustmentBean.getItems().stream()
                .filter((item) ->
                        item.getAdjustCost().compareTo(zeroVal) < 1
                                || item.getAdjustQty().compareTo(zeroVal) < 1
                                || item.getAdjustGiftQty().compareTo(zeroVal) < 0
                ).collect(Collectors.toList());

        if (existFilter.size() > 0) {
            StringBuilder sb = new StringBuilder();
            for (WebsitPurchaseAdjustmentItem purchaseAdjustmentItem : existFilter) {
                sb.append(purchaseAdjustmentItem.getGoodsId())
                        .append(" ")
                        .append(purchaseAdjustmentItem.getGoodsName())
                        .append("：");
                if (purchaseAdjustmentItem.getAdjustCost().compareTo(zeroVal) < 1) {
                    sb.append("调整进价不能少于等于0；");
                }
                if (purchaseAdjustmentItem.getAdjustQty().compareTo(zeroVal) < 1) {
                    sb.append("调整数量不能少于等于0；");
                }
                if (purchaseAdjustmentItem.getAdjustGiftQty().compareTo(zeroVal) < 0) {
                    sb.append("调整赠品数量不能少于0；");
                }
                sb.append("<br/><br/>");
            }
            sb.delete(sb.length()-10, sb.length());
            throw new RemoteServiceException(sb.toString());
        }

        // 查询明细表信息
        List<WebsitPurchaseAdjustmentItem> purchaseAdjustmentItems = websitPurchaseAdjustmentItemService.lambdaQuery()
                .eq(WebsitPurchaseAdjustmentItem::getPurchaseAdjustmentId, purchaseAdjustmentBean.getPurchaseAdjustmentId())
                .list();

        Map<String, WebsitPurchaseAdjustmentItem> goodsMap = purchaseAdjustmentBean.getItems().stream()
                .collect(Collectors.toMap((p) -> p.getPurchaseAdjustmentId() + "|" + p.getGoodsId(), Function.identity(), (key1, key2) -> key2));

        for (WebsitPurchaseAdjustmentItem realItem : purchaseAdjustmentItems) {
            WebsitPurchaseAdjustmentItem item = goodsMap.get(realItem.getPurchaseAdjustmentId() + "|" + realItem.getGoodsId());
            realItem.setAdjustCost(item.getAdjustCost());
            realItem.setAdjustQty(item.getAdjustQty());
            realItem.setAdjustGiftQty(item.getAdjustGiftQty());
        }

        purchaseAdjustmentBean.setItems(purchaseAdjustmentItems);
    }

    private void validGoodsCost(WebsitPurchaseAdjustmentBean purchaseAdjustmentBean) throws RemoteServiceException {
        List<WebsitGoods> list = websitGoodsService.lambdaQuery()
                .in(WebsitGoods::getGoodsId, purchaseAdjustmentBean.getItems().stream()
                        .map(WebsitPurchaseAdjustmentItem::getGoodsId)
                        .collect(Collectors.toList()))
                .list();

        Map<String, WebsitGoods> goodsMap = list.stream()
                .collect(Collectors.toMap(WebsitGoods::getGoodsId, Function.identity(), (key1, key2) -> key2));

        for (int i = 0; i < purchaseAdjustmentBean.getItems().size(); i++) {
            WebsitPurchaseAdjustmentItem item = purchaseAdjustmentBean.getItems().get(i);
            WebsitGoods goods = goodsMap.get(item.getGoodsId());
            String preStr = "第" + (i+1) + "行, ";
            if (Objects.nonNull(goods.getCostRangeMini())
                    && goods.getCostRangeMini().compareTo(BigDecimal.ZERO) > 0
                    && item.getAdjustCost().compareTo(goods.getCostRangeMini()) < 0) {
                throw new RemoteServiceException(preStr + "不能低于辅材资料最小进价范围值");
            }
            if (Objects.nonNull(goods.getCostRangeMax())
                    && goods.getCostRangeMax().compareTo(BigDecimal.ZERO) > 0
                    && item.getAdjustCost().compareTo(goods.getCostRangeMax()) > 0) {
                throw new RemoteServiceException(preStr + "不能高于辅材资料最大进价范围值");
            }

            item.setAdjustInStockCost(item.getAdjustCost());
            item.setAdjustInStockQty(item.getAdjustQty().add(item.getAdjustGiftQty()));
        }

    }

    @Transactional
    public void submit(String purchaseAdjustmentId) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        websitPurchaseAdjustmentService.lambdaUpdate()
                .eq(WebsitPurchaseAdjustment::getPurchaseAdjustmentId, purchaseAdjustmentId)
                .eq(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.SAVE.getKey())
                .set(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.SUBMIT.getKey())
                .set(WebsitPurchaseAdjustment::getSubmitBy, adminUser.getNickName())
                .set(WebsitPurchaseAdjustment::getSubmitTime, DateUtil.date())
                .update();
    }

    @Transactional
    public void revoke(String purchaseAdjustmentId) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        websitPurchaseAdjustmentService.lambdaUpdate()
                .eq(WebsitPurchaseAdjustment::getPurchaseAdjustmentId, purchaseAdjustmentId)
                .eq(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.SUBMIT.getKey())
                .set(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.SAVE.getKey())
                .set(WebsitPurchaseAdjustment::getUpdateBy, adminUser.getNickName())
                .set(WebsitPurchaseAdjustment::getUpdateTime, DateUtil.date())
                .update();
    }

    @Transactional
    public void del(String purchaseAdjustmentId) {
        websitPurchaseAdjustmentService.lambdaUpdate()
                .eq(WebsitPurchaseAdjustment::getPurchaseAdjustmentId, purchaseAdjustmentId)
                .eq(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.SAVE.getKey())
                .remove();

        websitPurchaseAdjustmentItemService.lambdaUpdate()
                .eq(WebsitPurchaseAdjustmentItem::getPurchaseAdjustmentId, purchaseAdjustmentId)
                .remove();
    }

    @Transactional
    public void confirm(String purchaseAdjustmentId) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        final boolean update = websitPurchaseAdjustmentService.lambdaUpdate()
                .eq(WebsitPurchaseAdjustment::getPurchaseAdjustmentId, purchaseAdjustmentId)
                .eq(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.SUBMIT.getKey())
                .set(WebsitPurchaseAdjustment::getFlag, MaterialFlagEnum.OK.getKey())
                .set(WebsitPurchaseAdjustment::getConfirmBy, adminUser.getNickName())
                .set(WebsitPurchaseAdjustment::getConfirmTime, DateUtil.date())
                .update();

        if (!update) {
            throw new RemoteServiceException("单据不存在或状态已发生变化");
        }
        WebsitPurchaseAdjustment purchaseAdjustment = websitPurchaseAdjustmentService.getById(purchaseAdjustmentId);

        // 获取调整明细
        List<WebsitPurchaseAdjustmentItem> purchaseAdjustmentItems = websitPurchaseAdjustmentItemService.lambdaQuery()
                .eq(WebsitPurchaseAdjustmentItem::getPurchaseAdjustmentId, purchaseAdjustment.getPurchaseAdjustmentId())
                .list();

        // 调整明细转为Map
        Map<String, WebsitPurchaseAdjustmentItem> goodsMap = purchaseAdjustmentItems.stream()
                .collect(Collectors.toMap(WebsitPurchaseAdjustmentItem::getGoodsId, Function.identity(), (key1, key2) -> key2));

        // 获取采购明细
        List<WebsitPurchaseItem> purchaseItems = websitPurchaseItemService.lambdaQuery()
                .eq(WebsitPurchaseItem::getPurchaseId, purchaseAdjustment.getRef())
                .list();

        List<WebsitPurchaseItem> changePurchaseList = new ArrayList<>();
        List<WebsitPurchaseAdjustmentItem> changeAdjustList = new ArrayList<>();

        // 遍历修改采购明细
        for (WebsitPurchaseItem purchaseItem : purchaseItems) {
            WebsitPurchaseAdjustmentItem item = goodsMap.get("" + purchaseItem.getGoodsId());

            if (purchaseItem.getCost().compareTo(item.getAdjustCost()) != 0
                    || purchaseItem.getRecQty().compareTo(item.getAdjustQty()) != 0
                    || purchaseItem.getRecGiftQty().compareTo(item.getAdjustGiftQty()) != 0) {
                // 进价或验收数量或验收赠品数量不等时执行变更
                purchaseItem.setCost(item.getAdjustCost());
                purchaseItem.setRecQty(item.getAdjustQty());
                purchaseItem.setRecGiftQty(item.getAdjustGiftQty());
                purchaseItem.setCostValue(item.getRecQty()
                        .multiply(item.getCost())
                        .setScale(2, BigDecimal.ROUND_DOWN));
                purchaseItem.setInStockQty(item.getAdjustInStockQty());
                purchaseItem.setInStockCost(item.getAdjustInStockCost());
                changePurchaseList.add(purchaseItem);
                changeAdjustList.add(item);
            }
        }

        // 更改采购明细信息
        websitPurchaseItemService.updateBatchById(changePurchaseList);

        if (changeAdjustList.size() > 0) {
            // 处理库存
            webitPurchaseStockLogic.adjustmentStock(purchaseAdjustment, changeAdjustList, "采购调整");
        }
    }
}
