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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
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.listvo.material.WorkerStockAccPVO;
import com.gree.mall.manager.bean.listvo.material.WorkerStockAccVO;
import com.gree.mall.manager.bean.listvo.material.WorkerStockPVO;
import com.gree.mall.manager.bean.listvo.material.WorkerStockVO;
import com.gree.mall.manager.bean.material.stock.WorkerStockDTO;
import com.gree.mall.manager.commonmapper.CommonMapper;
import com.gree.mall.manager.enums.material.DirectFlagEnum;
import com.gree.mall.manager.enums.material.PartsAttrEnum;
import com.gree.mall.manager.enums.material.WebsitGoodsTypeEnum;
import com.gree.mall.manager.enums.material.WorkerStockFlagEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.utils.CommonUtils;
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.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class WorkerStockLogic {

    private final CommonLogic commonLogic;
    private final CommonMapper commonMapper;
    private final WorkerGoodsService workerGoodsService;
    private final WorkerStockService workerStockService;
    private final WorkerStockAccService workerStockAccService;
    private final AdminWebsitService adminWebsitService;
    private final UserService userService;
    private final MaterialGoodsStockLogic materialGoodsStockLogic;
    private final WebsitGoodsService websitGoodsService;
    private final WorkerStockBakService workerStockBakService;
    private final WorkerStockAccBakService workerStockAccBakService;

    /**
     * 师傅辅材库存列表
     *
     * @param zfireParamBean
     * @return
     */
    public IPage<WorkerStockVO> workerStockList(ZfireParamBean zfireParamBean) {
        final AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.materialParam(zfireParamBean, WorkerStockVO.class, adminUser);

        IPage<WorkerStockVO> page = commonMapper.workerStockList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
        return page;
    }

    /**
     * 师傅辅材库存明细
     *
     * @param zfireParamBean
     * @return
     */
    public IPage<WorkerStockAccVO> workerStockAccList(ZfireParamBean zfireParamBean) {
        zfireParamBean.setCompanyWechatId(commonLogic.getAdminUser().getCompanyWechatId());
        FieldUtils.supplyParam(zfireParamBean, WorkerStockAccVO.class);
        IPage<WorkerStockAccVO> page = commonMapper.workerStockAccList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
        return page;
    }


    /**
     * 师傅配件库存列表
     *
     * @param zfireParamBean
     * @return
     */
    public IPage<WorkerStockPVO> workerStockPList(ZfireParamBean zfireParamBean) {
        final AdminUserCom adminUser = commonLogic.getAdminUser();
        zfireParamBean.setCompanyWechatId(commonLogic.getAdminUser().getCompanyWechatId());
        FieldUtils.supplyParam(zfireParamBean, WorkerStockPVO.class, adminUser);
        IPage<WorkerStockPVO> page = commonMapper.workerStockPList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
        return page;
    }

    /**
     * 师傅配件库存明细
     *
     * @param zfireParamBean
     * @return
     */
    public IPage<WorkerStockAccPVO> workerStockAccPList(ZfireParamBean zfireParamBean) {
        zfireParamBean.setCompanyWechatId(commonLogic.getAdminUser().getCompanyWechatId());
        FieldUtils.supplyParam(zfireParamBean, WorkerStockAccPVO.class);
        IPage<WorkerStockAccPVO> page = commonMapper.workerStockAccPList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
        return page;
    }


    /**
     * 导入师傅库存(各个商品只能导第一次)
     *
     * @param datas
     */
    @Transactional
    public void importData(List<Object> datas, WebsitGoodsTypeEnum websitGoodsTypeEnum) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        if (adminUser.getType() == 2) {
            throw new RemoteServiceException("平台账号禁止操作");
        }

        List<WorkerStockDTO> workerStockDTOS = new ArrayList<>();
        final DateTime curDate = DateUtil.date();
        final String idStr = IdWorker.getIdStr();

        String tipsGoodsName = websitGoodsTypeEnum.getKey().equals(WebsitGoodsTypeEnum.M.getKey()) ? "辅材" : "配件";

        for (int i = 0; i < datas.size(); i++) {
            List<String> row = (List<String>) datas.get(i);
            CommonUtils.initList(row, 10);
            if (websitGoodsTypeEnum.getKey().equals(WebsitGoodsTypeEnum.M.getKey())) {
                String goodsId = row.get(0);
                String workerNumber = row.get(1);
                String qty = row.get(2);
                String price = row.get(3);
                if (StringUtils.isAnyBlank(goodsId, workerNumber, qty, price)) {
                    throw new RemoteServiceException("第" + (i + 1) + "行请补充完整内容");
                }
                WorkerGoods workerGoods = workerGoodsService.lambdaQuery()
                        .eq(WorkerGoods::getCompanyWechatId, adminUser.getCompanyWechatId())
                        .eq(WorkerGoods::getGoodsId, goodsId)
                        .one();
                if (workerGoods == null) {
                    throw new RemoteServiceException(tipsGoodsName + "编号【" + goodsId + "】不存在");
                }

                //判断师傅信息
                User user = userService.lambdaQuery()
                        .eq(User::getWorkerNumber, workerNumber)
                        .eq(User::getCompanyWechatId, adminUser.getCompanyWechatId())
                        .last("limit 1")
                        .one();
                if (user == null) {
                    throw new RemoteServiceException("师傅编号【" + workerNumber + "】不存在");
                }
                Integer count = workerStockService.lambdaQuery()
                        .eq(WorkerStock::getCompanyWechatId, adminUser.getCompanyWechatId())
                        .eq(WorkerStock::getWorkerId, user.getUserId())
                        .eq(WorkerStock::getGoodsId, goodsId).count();
                if (count > 0) {
                    throw new RemoteServiceException(tipsGoodsName + "编号【" + goodsId + "】的库存记录已存在于系统，导入失败");
                }

                WorkerStockDTO workerStockDTO = new WorkerStockDTO();
                workerStockDTO.setCompanyWechatId(adminUser.getCompanyWechatId());
                workerStockDTO.setCompanyWechatName(adminUser.getCompanyName());
                workerStockDTO.setIdentity(user.getIdCard());
                workerStockDTO.setWorkerId(user.getWorkerNumber());
                workerStockDTO.setWorkerName(user.getNickName());
                workerStockDTO.setSdate(curDate);
                workerStockDTO.setGoodsId(goodsId);
                workerStockDTO.setGoodsName(workerGoods.getGoodsName());
                workerStockDTO.setGoodsType(WebsitGoodsTypeEnum.M.getKey());
                workerStockDTO.setPrice(new BigDecimal(price));
                workerStockDTO.setGoodsStockUnit(workerGoods.getSalesUnit());
                workerStockDTO.setRef(idStr);
                workerStockDTO.setRefType("库存导入");
                workerStockDTO.setPartsAttr(PartsAttrEnum.NEW.getKey());
                workerStockDTO.setChangeQty(new BigDecimal(qty));
                workerStockDTO.setDirectFlag(DirectFlagEnum.ADD.getKey());
                workerStockDTO.setFlag(WorkerStockFlagEnum.INIT.getKey());
                workerStockDTO.setObj("师傅");
                workerStockDTO.setWorkerOrderNo("");
                workerStockDTO.setOperateBy(adminUser.getJoinNickName());
                workerStockDTO.setOperateTime(curDate);
                workerStockDTOS.add(workerStockDTO);
            } else {
                String goodsId = row.get(0);
                String stock = row.get(1);
                String oldQty = row.get(2);
                //String websitName = row.get(4);
                String workerId = row.get(4);
                if (StringUtils.isAnyBlank(goodsId, stock, oldQty, workerId)) {
                    throw new RemoteServiceException("第" + (i + 1) + "行请补充完整内容");
                }
                WebsitGoods websitGoods = websitGoodsService.lambdaQuery()
                        .eq(WebsitGoods::getCompanyWechatId, adminUser.getCompanyWechatId())
                        .eq(WebsitGoods::getGoodsType, websitGoodsTypeEnum.getKey())
                        .eq(WebsitGoods::getGoodsCode, goodsId)
                        .one();
                if (websitGoods == null) {
                    throw new RemoteServiceException(tipsGoodsName + "编号【" + goodsId + "】不存在");
                }

                //判断师傅信息
                User user = userService.lambdaQuery()
                        .eq(User::getWorkerNumber, workerId)
                        .eq(User::getCompanyWechatId, adminUser.getCompanyWechatId())
                        .last("limit 1")
                        .one();
                if (user == null) {
                    throw new RemoteServiceException("师傅编号【" + workerId + "】不存在");
                }
                Integer count = workerStockService.lambdaQuery()
                        .eq(WorkerStock::getCompanyWechatId, adminUser.getCompanyWechatId())
                        .eq(WorkerStock::getWorkerId, user.getWorkerNumber())
                        .eq(WorkerStock::getGoodsId, goodsId)
                        .count();
                if (count > 0) {
                    throw new RemoteServiceException(tipsGoodsName + "编号【" + goodsId + "】的库存记录已存在于系统，导入失败");
                }

                if (new BigDecimal(stock).compareTo(BigDecimal.ZERO) > 0) {
                    WorkerStockDTO workerStockDTO = new WorkerStockDTO();
                    workerStockDTO.setCompanyWechatId(adminUser.getCompanyWechatId());
                    workerStockDTO.setCompanyWechatName(adminUser.getCompanyName());
                    workerStockDTO.setIdentity(user.getIdCard());
                    workerStockDTO.setWorkerId(user.getWorkerNumber());
                    workerStockDTO.setWorkerName(user.getNickName());
                    workerStockDTO.setSdate(curDate);
                    workerStockDTO.setGoodsId(websitGoods.getGoodsId());
                    workerStockDTO.setGoodsName(websitGoods.getGoodsName());
                    workerStockDTO.setGoodsType(WebsitGoodsTypeEnum.P.getKey());
                    workerStockDTO.setGoodsStockUnit(websitGoods.getGoodsSalesUnit());
                    workerStockDTO.setRef(idStr);
                    workerStockDTO.setRefType("库存导入");
                    workerStockDTO.setPartsAttr(PartsAttrEnum.NEW.getKey());
                    workerStockDTO.setChangeQty(new BigDecimal(stock));
                    workerStockDTO.setDirectFlag(DirectFlagEnum.ADD.getKey());
                    workerStockDTO.setFlag(WorkerStockFlagEnum.INIT.getKey());
                    workerStockDTO.setObj("师傅");
                    workerStockDTO.setWorkerOrderNo("");
                    workerStockDTO.setOperateBy(adminUser.getJoinNickName());
                    workerStockDTO.setOperateTime(curDate);
                    workerStockDTOS.add(workerStockDTO);
                }


                if (new BigDecimal(oldQty).compareTo(BigDecimal.ZERO) > 0) {
                    WorkerStockDTO workerStockDTO2 = new WorkerStockDTO();
                    workerStockDTO2.setCompanyWechatId(adminUser.getCompanyWechatId());
                    workerStockDTO2.setCompanyWechatName(adminUser.getCompanyName());
                    workerStockDTO2.setIdentity(user.getIdCard());
                    workerStockDTO2.setWorkerId(user.getWorkerNumber());
                    workerStockDTO2.setWorkerName(user.getNickName());
                    workerStockDTO2.setSdate(curDate);
                    workerStockDTO2.setGoodsId(websitGoods.getGoodsId());
                    workerStockDTO2.setGoodsName(websitGoods.getGoodsName());
                    workerStockDTO2.setGoodsType(WebsitGoodsTypeEnum.P.getKey());
                    workerStockDTO2.setGoodsStockUnit(websitGoods.getGoodsSalesUnit());
                    workerStockDTO2.setRef(idStr);
                    workerStockDTO2.setRefType("库存导入");
                    workerStockDTO2.setPartsAttr(PartsAttrEnum.OLD.getKey());
                    workerStockDTO2.setChangeQty(new BigDecimal(oldQty));
                    workerStockDTO2.setDirectFlag(DirectFlagEnum.ADD.getKey());
                    workerStockDTO2.setFlag(WorkerStockFlagEnum.INIT.getKey());
                    workerStockDTO2.setObj("师傅");
                    workerStockDTO2.setWorkerOrderNo("");
                    workerStockDTO2.setOperateBy(adminUser.getJoinNickName());
                    workerStockDTO2.setOperateTime(curDate);
                    workerStockDTOS.add(workerStockDTO2);
                }

            }
        }
        // 开始处理库存
        materialGoodsStockLogic.handleWorkerStock(workerStockDTOS);
    }

    @Transactional
    public void delStock(List<String> ids) {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        if (adminUser.getType() == 2) {
            throw new RemoteServiceException("平台账号禁止操作");
        }
        final List<WorkerStock> stockList = workerStockService.lambdaQuery()
                .eq(WorkerStock::getCompanyWechatId, adminUser.getCompanyWechatId())
                .in(WorkerStock::getId, ids)
                .eq(WorkerStock::getGoodsType, WebsitGoodsTypeEnum.M.getKey())
                .list();

        if (CollectionUtil.isNotEmpty(stockList)) {
            final DateTime curDate = DateUtil.date();
            List<WorkerStockBak> workerStockBakList = new ArrayList<>();
            List<WorkerStockAccBak> workerStockAccBakList = new ArrayList<>();

            List<WorkerStockAcc> workerStockRemoveAccs = new ArrayList<>();
            // 按师傅分组
            final Map<String, List<WorkerStock>> workerGroupMap = stockList.stream()
                    .collect(Collectors.groupingBy(WorkerStock::getWorkerId));

            for (Map.Entry<String, List<WorkerStock>> workerStock : workerGroupMap.entrySet()) {
                // 需要删除的商品编号
                final List<String> goodsIds = workerStock.getValue().stream()
                        .map(WorkerStock::getGoodsId).collect(Collectors.toList());
                final List<WorkerStockAcc> workerStockAccs = workerStockAccService.lambdaQuery()
                        .eq(WorkerStockAcc::getCompanyWechatId, adminUser.getCompanyWechatId())
                        .in(WorkerStockAcc::getGoodsId, goodsIds)
                        .list();

                for (WorkerStock stock : workerStock.getValue()) {
                    WorkerStockBak workerStockBak = new WorkerStockBak();
                    BeanUtils.copyProperties(stock, workerStockBak);
                    workerStockBak.setOperBy(adminUser.getJoinNickName())
                            .setOperTime(curDate);
                    workerStockBakList.add(workerStockBak);
                }

                for (WorkerStockAcc stockAcc : workerStockAccs) {
                    WorkerStockAccBak workerStockaccBak = new WorkerStockAccBak();
                    BeanUtils.copyProperties(stockAcc, workerStockaccBak);
                    workerStockAccBakList.add(workerStockaccBak);
                }

                if (CollectionUtil.isNotEmpty(workerStockAccs)) {
                    workerStockRemoveAccs.addAll(workerStockAccs);
                }
            }

            workerStockService.removeByIds(stockList.stream().map(WorkerStock::getId).collect(Collectors.toList()));
            workerStockAccService.removeByIds(workerStockRemoveAccs.stream().map(WorkerStockAcc::getId).collect(Collectors.toList()));
            workerStockBakService.saveBatch(workerStockBakList);
            workerStockAccBakService.saveBatch(workerStockAccBakList);
        }
    }
}
