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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReUtil;
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.WebsitNewInListBean;
import com.gree.mall.manager.bean.material.manage.WebsitPartsNewInRecordDTO;
import com.gree.mall.manager.bean.material.manage.WebsitPartsNewInVO;
import com.gree.mall.manager.commonmapper.MaterialMapper;
import com.gree.mall.manager.enums.IsEnum;
import com.gree.mall.manager.enums.material.NormTypeEnum;
import com.gree.mall.manager.enums.material.PartsCheckStatusEnum;
import com.gree.mall.manager.enums.material.WebsitGoodsTypeEnum;
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.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class WebsitPartsNewInLogic {

    private final CommonLogic commonLogic;
    private final MaterialMapper materialMapper;
    private final WebsitPartsNewInRecordService websitPartsNewInRecordService;
    private final AdminWebsitService adminWebsitService;
    private final WebsitGoodsService websitGoodsService;
    private final WebitPurchaseStockLogic webitPurchaseStockLogic;
    private final StorageService storageService;
    private final WebsitPartsNewInRecordBakService websitPartsNewInRecordBakService;

    public IPage<WebsitPartsNewInVO> pageList(ZfireParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.materialParam(zfireParamBean, WebsitPartsNewInVO.class, adminUser);
        IPage<WebsitPartsNewInVO> page = materialMapper.websitPartsNewInPage(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
        return page;
    }

    @Transactional
    public void importNewIn(List<Object> objects) {
        if (objects.size() > 0) {
            // 注入对象
            List<WebsitPartsNewInRecordDTO> newInRecordDTOList = this.handleNewInRecordObj(objects);
            for (WebsitPartsNewInRecordDTO newInRecordDTO : newInRecordDTOList) {
                Integer count = websitPartsNewInRecordService.lambdaQuery()
                        .eq(WebsitPartsNewInRecord::getSysNo, newInRecordDTO.getSysNo())
                        .count();
                if (count > 0) {
                    // 已经处理过的系统序号就跳过
                    continue;
                }
                websitPartsNewInRecordService.save(newInRecordDTO);
            }
        }
    }

    private List<WebsitPartsNewInRecordDTO> handleNewInRecordObj(List<Object> objects) {
        DateTime curDate = DateUtil.date();
        AdminUserCom adminUser = commonLogic.getAdminUser();

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

        final List<AdminWebsit> websitList = adminWebsitService.lambdaQuery()
                .in(AdminWebsit::getWebsitId, adminUser.getAdminWebsitIds())
                .isNotNull(AdminWebsit::getPartsWebsitId)
                .list();

        Map<String, AdminWebsit> websitMap = websitList.stream()
                .collect(Collectors.toMap(AdminWebsit::getPartsWebsitId, Function.identity()));

        // 查询配件资料
        final List<WebsitGoods> partsList = websitGoodsService.lambdaQuery()
                .in(WebsitGoods::getGoodsCode, objects.stream()
                        .map(v -> (Optional.ofNullable(((List<Object>) v).get(4))).orElse(""))
                        .collect(Collectors.toSet()))
                .eq(WebsitGoods::getGoodsType, WebsitGoodsTypeEnum.P.getKey())
                .eq(WebsitGoods::getNormType, NormTypeEnum.M.getKey())
                .list();

        Map<String, WebsitGoods> partsMap = partsList.stream()
                .collect(Collectors.toMap(WebsitGoods::getGoodsCode, Function.identity()));

        final List<Storage> storageList = storageService.lambdaQuery()
                .eq(Storage::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                .in(Storage::getWebsitId, adminUser.getAdminWebsitIds())
                .eq(Storage::getIsDefault, IsEnum.Y.getValue())
                .list();

        Map<String, Storage> storageMap = storageList.stream()
                .collect(Collectors.toMap(Storage::getWebsitId, Function.identity()));

        List<WebsitPartsNewInRecordDTO> inRecordDTOS = new ArrayList<>();
        for (int i = 1; i < objects.size(); i++) {
            List<Object> row = (List<Object>) objects.get(i);
            String voucherNo = (String) row.get(0);
            String applyNo = (String) row.get(1);
            String remark = (String) row.get(2);
            String objectType = (String) row.get(3);
            String partsNumber = (String) row.get(4);
            String priceStr = (String) row.get(7);
            String qtyStr = (String) row.get(8);
            String newNo = (String) row.get(9);
            String primaryPriceStr = (String) row.get(10);
            String discPriceStr = (String) row.get(11);
            String realPriceStr = (String) row.get(12);
            String diffPriceStr = (String) row.get(13);
            String sendUnit = (String) row.get(14);
            String receiveUnit = (String) row.get(15);
            String orderDateStr = (String) row.get(16);
            String sysNo = (String) row.get(17);
            String receiveDate = (String) row.get(18);
            String operateBy = (String) row.get(19);
            String sendUnitArea = (String) row.get(20);
            String receiveUnitArea = (String) row.get(21);
            String repairCustomNo = (String) row.get(22);
            if (StringUtils.isBlank(objectType) || !"新件申领".contains(objectType)) {
                throw new RemoteServiceException("第" + (i+2) + "行，事物类型格式不符，只能是“新件申领”");
            }
            if (StringUtils.isBlank(voucherNo)) {
                throw new RemoteServiceException("第" + (i+2) + "行，凭证号不能为空");
            }
            if (StringUtils.isBlank(partsNumber)) {
                throw new RemoteServiceException("第" + (i+2) + "行，配件编码不能为空");
            }
            if (StringUtils.isBlank(receiveUnit) || receiveUnit.indexOf(":") <= 0) {
                throw new RemoteServiceException("第" + (i+2) + "行，领入单位格式不符");
            }
            if (StringUtils.isBlank(orderDateStr) || !ReUtil.isMatch("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{1,2}:\\d{1,2}", orderDateStr)) {
                throw new RemoteServiceException("第" + (i+1) + "行，开单日期格式不符");
            }
            String receiveUnitNumber = receiveUnit.split(":")[0];
            AdminWebsit receiveShop = websitMap.get(receiveUnitNumber);
            WebsitGoods parts = partsMap.get(partsNumber);
            if (Objects.isNull(receiveShop)) {
//                throw new RemoteServiceException("第" + (i+2) + "行，领入单位未配置");
                continue;
            }
            if (Objects.isNull(parts)) {
                throw new RemoteServiceException("第" + (i+2) + "行，配件编码未配置");
            }
            if (StringUtils.isBlank(sysNo)) {
                throw new RemoteServiceException("第" + (i+2) + "行，系统序号不能为空");
            }
            final Storage storage = storageMap.get(receiveShop.getWebsitId());

            WebsitPartsNewInRecordDTO partsShopNewInRecordDTO = new WebsitPartsNewInRecordDTO();
            partsShopNewInRecordDTO.setVoucherNo(voucherNo)
                    .setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId())
                    .setCompanyWechatName(adminUser.getAdminCompanyWechat().getCompanyName())
                    .setApplyNo(applyNo)
                    .setRemark(remark)
                    .setObjectType(objectType.trim())
                    .setGoodsId(parts.getGoodsId())
                    .setPartsNumber(partsNumber)
                    .setPartsName(parts.getGoodsName())
                    .setMaterialGroupName(parts.getMaterialGroupName())
                    .setGoodsStockUnit(parts.getGoodsStockUnit())
                    .setPrice(new BigDecimal(StringUtils.isNotBlank(priceStr) ? priceStr : "0"))
                    .setQty(new BigDecimal(StringUtils.isNotBlank(qtyStr) ? qtyStr : "0"))
                    .setNewNo(newNo)
                    .setPrimaryPrice(new BigDecimal(StringUtils.isNotBlank(primaryPriceStr) ? primaryPriceStr : "0"))
                    .setDiscPrice(new BigDecimal(StringUtils.isNotBlank(discPriceStr) ? discPriceStr : "0"))
                    .setRealPrice(new BigDecimal(StringUtils.isNotBlank(realPriceStr) ? realPriceStr : "0"))
                    .setDiffPrice(new BigDecimal(StringUtils.isNotBlank(diffPriceStr) ? diffPriceStr : "0"))
                    .setSendUnit(sendUnit)
                    .setReceiveUnit(receiveUnit)
                    .setSendWebsitId("")
                    .setSendWebsitName("")
                    .setReceiveWebsitId(receiveShop.getWebsitId())
                    .setReceiveWebsitName(receiveShop.getName())
                    .setReceivePartsWebsitId(receiveShop.getPartsWebsitId())
                    .setOrderDate(StringUtils.isNotBlank(orderDateStr) ? DateUtil.parseDateTime(orderDateStr) : null)
                    .setSysNo(sysNo)
                    .setReceiveDate(StringUtils.isNotBlank(receiveDate) ? DateUtil.parseDate(receiveDate) : null)
                    .setOperateBy(operateBy)
                    .setSendUnitArea(sendUnitArea)
                    .setReceiveUnitArea(receiveUnitArea)
                    .setRepairCustomNo(repairCustomNo)
                    .setImportDate(curDate)
                    .setStatus(PartsCheckStatusEnum.WAIT_CHECK.getKey())
                    .setStorageId(storage.getStorageId())
                    .setStorageName(storage.getStorageName());
            partsShopNewInRecordDTO.setAdminWebsit(receiveShop);
            inRecordDTOS.add(partsShopNewInRecordDTO);
        }

        return inRecordDTOS;
    }

    @Transactional
    public void add(List<WebsitNewInListBean> websitNewInListBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        if (adminUser.getType() == 2) {
            throw new RemoteServiceException("平台账号禁止操作");
        }
        final List<AdminWebsit> websitList = adminWebsitService.lambdaQuery()
                .in(AdminWebsit::getWebsitId, adminUser.getAdminWebsitIds())
                .isNotNull(AdminWebsit::getPartsWebsitId)
                .list();

        Map<String, AdminWebsit> websitMap = websitList.stream()
                .collect(Collectors.toMap(AdminWebsit::getPartsWebsitId, Function.identity()));

        // 查询配件资料
        final List<WebsitGoods> partsList = websitGoodsService.lambdaQuery()
                .in(WebsitGoods::getGoodsCode, websitNewInListBean.stream()
                        .map(WebsitNewInListBean::getPartsNumber)
                        .collect(Collectors.toSet()))
                .eq(WebsitGoods::getGoodsType, WebsitGoodsTypeEnum.P.getKey())
                .eq(WebsitGoods::getNormType, NormTypeEnum.M.getKey())
                .list();

        Map<String, WebsitGoods> partsMap = partsList.stream()
                .collect(Collectors.toMap(WebsitGoods::getGoodsCode, Function.identity()));

        final List<Storage> storageList = storageService.lambdaQuery()
                .eq(Storage::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                .in(Storage::getWebsitId, adminUser.getAdminWebsitIds())
                .eq(Storage::getIsDefault, IsEnum.Y.getValue())
                .list();

        Map<String, Storage> storageMap = storageList.stream()
                .collect(Collectors.toMap(Storage::getWebsitId, Function.identity()));

        List<WebsitPartsNewInRecord> partsShopNewInRecordList = new ArrayList<>();
        for (WebsitNewInListBean newInListBean : websitNewInListBean) {
            WebsitPartsNewInRecord partsShopNewInRecord = new WebsitPartsNewInRecord();
            AdminWebsit websit = websitMap.get(newInListBean.getReceivePartsWebsiteNumber());
            if (Objects.isNull(websit)) {
                throw new RemoteServiceException(newInListBean.getPartsNumber() + "：未找到网点信息");
            }
            WebsitGoods parts = partsMap.get(newInListBean.getPartsNumber());
            if (Objects.isNull(parts)) {
                throw new RemoteServiceException(newInListBean.getPartsNumber() + "：未找到配件编码");
            }
            final Storage storage = storageMap.get(websit.getWebsitId());
            partsShopNewInRecord.setId(IdWorker.getIdStr())
                    .setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId())
                    .setCompanyWechatName(adminUser.getAdminCompanyWechat().getCompanyName())
                    .setVoucherNo(IdWorker.getIdStr())
                    .setApplyNo(IdWorker.getIdStr())
                    .setRemark(newInListBean.getRemark())
                    .setObjectType("新件入库")
                    .setGoodsId(parts.getGoodsId())
                    .setPartsNumber(newInListBean.getPartsNumber())
                    .setPartsName(parts.getGoodsName())
                    .setMaterialGroupName(parts.getMaterialGroupName())
                    .setGoodsStockUnit(parts.getGoodsStockUnit())
                    .setPrice(newInListBean.getPrice())
                    .setQty(newInListBean.getQty())
                    .setReceiveWebsitId(websit.getWebsitId())
                    .setReceiveWebsitName(websit.getName())
                    .setReceivePartsWebsitId(websit.getPartsWebsitId())
                    .setOrderDate(DateUtil.date())
                    .setSysNo(IdWorker.getIdStr())
                    .setOperateBy(adminUser.getNickName())
                    .setStatus(PartsCheckStatusEnum.WAIT_CHECK.getKey())
                    .setStorageId(storage.getStorageId())
                    .setStorageName(storage.getStorageName());

            partsShopNewInRecordList.add(partsShopNewInRecord);
        }
        websitPartsNewInRecordService.saveBatch(partsShopNewInRecordList);
    }

    @Transactional
    public void updateIn(List<String> ids) throws Exception {
        DateTime curDate = DateUtil.date();
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<WebsitPartsNewInRecord> partsShopNewInRecords = websitPartsNewInRecordService.lambdaQuery()
                .in(WebsitPartsNewInRecord::getId, ids)
                .list();

        if (CollectionUtil.isNotEmpty(partsShopNewInRecords)) {
            final List<WebsitPartsNewInRecord> collect = partsShopNewInRecords.stream()
                    .peek(v -> v.setCheckBy(adminUser.getNickName())
                            .setCheckTime(curDate)
                            .setStatus(PartsCheckStatusEnum.CHECKED.getKey()))
                    .collect(Collectors.toList());
            Map<String, List<WebsitPartsNewInRecord>> listMap = collect.stream()
                    .collect(Collectors.groupingBy(WebsitPartsNewInRecord::getReceiveWebsitId));

            for (List<WebsitPartsNewInRecord> shopNewInRecords : listMap.values()) {
                webitPurchaseStockLogic.newInStock(shopNewInRecords);
            }
            websitPartsNewInRecordService.saveOrUpdateBatch(collect);
        }
    }

    public void delNewIn(List<String> ids) {
        List<WebsitPartsNewInRecord> partsShopNewInRecords = websitPartsNewInRecordService.lambdaQuery()
                .in(WebsitPartsNewInRecord::getId, ids)
                .eq(WebsitPartsNewInRecord::getStatus, PartsCheckStatusEnum.WAIT_CHECK.getKey())
                .list();

        websitPartsNewInRecordService.lambdaUpdate()
                .in(WebsitPartsNewInRecord::getId, ids)
                .eq(WebsitPartsNewInRecord::getStatus, PartsCheckStatusEnum.WAIT_CHECK.getKey())
                .remove();

        List<WebsitPartsNewInRecordBak> partsShopNewInRecordBakList = new ArrayList<>();
        for (WebsitPartsNewInRecord websitPartsNewInRecord : partsShopNewInRecords) {
            WebsitPartsNewInRecordBak partsShopNewInRecordBak = new WebsitPartsNewInRecordBak();
            BeanUtils.copyProperties(websitPartsNewInRecord, partsShopNewInRecordBak);
            partsShopNewInRecordBakList.add(partsShopNewInRecordBak);
        }
        websitPartsNewInRecordBakService.saveBatch(partsShopNewInRecordBakList);
    }
}
