package com.gree.mall.miniapp.logic.material.parts;

import cn.hutool.core.collection.CollectionUtil;
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.miniapp.bean.material.parts.NewRefundManageBean;
import com.gree.mall.miniapp.bean.material.parts.NewRefundManageItemBean;
import com.gree.mall.miniapp.bean.material.parts.PartsRefundRecordDTO;
import com.gree.mall.miniapp.bean.material.stock.WorkerStockDTO;
import com.gree.mall.miniapp.bean.user.CurrentCompanyWechat;
import com.gree.mall.miniapp.commonmapper.MaterialMapper;
import com.gree.mall.miniapp.enums.PayTypeEnum;
import com.gree.mall.miniapp.enums.admin.AdminWebsitTypeEnum;
import com.gree.mall.miniapp.enums.material.*;
import com.gree.mall.miniapp.exception.RemoteServiceException;
import com.gree.mall.miniapp.logic.common.CommonLogic;
import com.gree.mall.miniapp.logic.material.stock.MaterialGoodsStockLogic;
import com.gree.mall.miniapp.plus.entity.*;
import com.gree.mall.miniapp.plus.service.AdminWebsitService;
import com.gree.mall.miniapp.plus.service.WebsitPartsNewRefundManageItemService;
import com.gree.mall.miniapp.plus.service.WebsitPartsNewRefundManageRecordService;
import com.gree.mall.miniapp.plus.service.WebsitPartsSalesItemService;
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 javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class NewRefundManageLogic {

    @Resource
    CommonLogic commonLogic;
    @Resource
    MaterialMapper materialMapper;
    @Resource
    AdminWebsitService adminWebsitService;
    @Resource
    WebsitPartsSalesItemService websitPartsSalesItemService;
    @Resource
    WebsitPartsNewRefundManageItemService websitPartsNewRefundManageItemService;
    @Resource
    WebsitPartsNewRefundManageRecordService websitPartsNewRefundManageRecordService;
    @Resource
    MaterialGoodsStockLogic materialGoodsStockLogic;

    public IPage<NewRefundManageBean> appList(String applyNo, String flag, String identity, String partsNumber, Integer pageNo, Integer pageSize) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        IPage<NewRefundManageBean> page = materialMapper.appList(new Page(pageNo, pageSize), wechat.getCompanyWechatId(), applyNo, flag, identity, partsNumber);
        return page;
    }

    public NewRefundManageBean detail(String applyNo) {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        IPage<NewRefundManageBean> page = materialMapper.appList(new Page(1, -1), wechat.getCompanyWechatId(), applyNo, null, null, null);
        if (CollectionUtil.isEmpty(page.getRecords())) {
            throw new RemoteServiceException("单据不存在");
        }
        NewRefundManageBean newRefundManageBean = page.getRecords().get(0);
        return newRefundManageBean;
    }

    @Transactional
    public void add(NewRefundManageBean newRefundManageBean) throws Exception {
        final CurrentCompanyWechat wechat = commonLogic.getCurrentCompanyWechat();
        newRefundManageBean.setCompanyWechatId(wechat.getCompanyWechatId())
                .setCompanyWechatName(wechat.getCompanyName());
        // 查询接收网点
        AdminWebsit websit = adminWebsitService.lambdaQuery()
                .eq(AdminWebsit::getCompanyWechatId, newRefundManageBean.getCompanyWechatId())
                .eq(AdminWebsit::getWebsitId, newRefundManageBean.getReceiveWebsitId())
                .eq(AdminWebsit::getStatus, Boolean.TRUE)
                .eq(AdminWebsit::getType, AdminWebsitTypeEnum.C.getKey())
                .one();
        if (Objects.isNull(websit)) {
            throw new RemoteServiceException("接收网点不存在");
        }
        // 查询师傅在接收网点的库存
        List<WebsitPartsSalesItem> salesOrderItems = websitPartsSalesItemService.lambdaQuery()
                .eq(WebsitPartsSalesItem::getSalesId, newRefundManageBean.getSalesId())
                .list();
        Map<String, WebsitPartsSalesItem> workerStockMap = salesOrderItems.stream()
                .collect(Collectors.toMap(WebsitPartsSalesItem::getPartsNumber, Function.identity()));
        for (NewRefundManageItemBean itemBean : newRefundManageBean.getNewRefundManageItemBeanList()) {
            WebsitPartsSalesItem workerStock = workerStockMap.get(itemBean.getPartsNumber());
            if (Objects.isNull(workerStock)) {
                throw new RemoteServiceException("“" + itemBean.getPartsName() + "”配件未找到记录");
            }
            if (itemBean.getQty().compareTo(workerStock.getQty()) > 0) {
                throw new RemoteServiceException("“" + workerStock.getPartsName() + "”归还新件数量不能大于销售单剩余数量");
            }
            if (itemBean.getQty().compareTo(BigDecimal.ZERO) < 1) {
                throw new RemoteServiceException("“" + workerStock.getPartsName() + "”归还新件数量必须大于0");
            }
        }
        String sheetId = commonLogic.generateMaterialNo(newRefundManageBean.getCompanyWechatId(), "XH", PartsRefTypeEnum.NEW_REFUND.getKey(), 13);
        newRefundManageBean.setApplyNo(sheetId);
        newRefundManageBean.setReceiveWebsitName(websit.getName());
        newRefundManageBean.setReceivePartsWebsitId(websit.getPartsWebsitId());
        newRefundManageBean.setWebsitAddress(websit.getAddress());
        newRefundManageBean.setCreateTime(DateUtil.date());
        newRefundManageBean.setUpdateTime(DateUtil.date());
        newRefundManageBean.setSubmitBy(newRefundManageBean.getWorkerName());
        newRefundManageBean.setSubmitTime(DateUtil.date());
        newRefundManageBean.setFlag(PartsOrderFlagEnum.SUBMIT.getKey());

        // 保存主表和明细
        WebsitPartsNewRefundManage partsNewRefundManage = new WebsitPartsNewRefundManage();
        BeanUtils.copyProperties(newRefundManageBean, partsNewRefundManage);
        List<WebsitPartsNewRefundManageItem> partsNewRefundManageItems = new ArrayList<>();
        for (NewRefundManageItemBean itemBean : newRefundManageBean.getNewRefundManageItemBeanList()) {
            WebsitPartsNewRefundManageItem partsNewRefundManageItem = new WebsitPartsNewRefundManageItem();
            itemBean.setId(IdWorker.getIdStr());
            itemBean.setApplyNo(sheetId);
            BeanUtils.copyProperties(itemBean, partsNewRefundManageItem);
            partsNewRefundManageItem.setSalesId(newRefundManageBean.getSalesId());
            partsNewRefundManageItems.add(partsNewRefundManageItem);
        }
        partsNewRefundManage.insert();
        websitPartsNewRefundManageItemService.saveBatch(partsNewRefundManageItems);
        // 提交 暂扣师傅新件库存 增加师傅临占新件库存
        List<WorkerStockDTO> workerStockDTOList = this.createWorkerStockDTO(partsNewRefundManage, partsNewRefundManageItems,
                partsNewRefundManage.getWorkerName(), partsNewRefundManage.getUpdateTime(), PartsAttrEnum.NEW.toString(), PartsAttrEnum.TEMP_NEW.toString());
        materialGoodsStockLogic.handleWorkerStock(workerStockDTOList);

        // 查找销售单并减掉相应数量
        List<PartsRefundRecordDTO> partsRefundRecordDTOList = materialGoodsStockLogic.handleNewRefundWebsitPartsSales(partsNewRefundManage.getReceiveWebsitId(), partsNewRefundManage.getReceivePartsWebsitId(),
                partsNewRefundManage.getIdentity(), partsNewRefundManageItems, PartsRefTypeEnum.NEW_REFUND.getKey());
        List<WebsitPartsNewRefundManageRecord> partsNewRefundManageRecordList = new ArrayList<>();
        BigDecimal refundAmount = BigDecimal.ZERO;
        for (PartsRefundRecordDTO partsRefundRecordDTO : partsRefundRecordDTOList) {
            WebsitPartsNewRefundManageRecord refundManageRecord = new WebsitPartsNewRefundManageRecord();
            BeanUtils.copyProperties(partsRefundRecordDTO, refundManageRecord);
            if (refundManageRecord.getRefundAmountMode().equals(PayTypeEnum.CASH.getKey())) {
                refundManageRecord.setRefundState(PartsRefundStateEnum.OK.getKey());
            }
            refundAmount = refundAmount.add(refundManageRecord.getRefundAmount());
            partsNewRefundManageRecordList.add(refundManageRecord);
        }

        // 更新新件返还主表退款金额
        partsNewRefundManage.setRefundAmount(refundAmount)
                .updateById();
        // 保存新件返还销售明细记录
        websitPartsNewRefundManageRecordService.saveBatch(partsNewRefundManageRecordList);
    }

    private List<WorkerStockDTO> createWorkerStockDTO(WebsitPartsNewRefundManage partsNewRefundManage,
                                                      List<WebsitPartsNewRefundManageItem> partsNewRefundManageItems,
                                                      String operateBy, Date operateTime, String partsAttr1,
                                                      String partsAttr2) {
        List<WorkerStockDTO> workerStockDTOList = new ArrayList<>();

        for (WebsitPartsNewRefundManageItem refundManageItem : partsNewRefundManageItems) {
            // 新件
            if (StringUtils.isNotBlank(partsAttr1)) {
                WorkerStockDTO workerStockDTO = new WorkerStockDTO();
                workerStockDTO.setCompanyWechatId(partsNewRefundManage.getCompanyWechatId());
                workerStockDTO.setCompanyWechatName(partsNewRefundManage.getCompanyWechatName());
                workerStockDTO.setIdentity(partsNewRefundManage.getIdentity());
                workerStockDTO.setWorkerId(partsNewRefundManage.getWorkerId());
                workerStockDTO.setWorkerName(partsNewRefundManage.getWorkerName());
                workerStockDTO.setWebsitId(partsNewRefundManage.getReceiveWebsitId());
                workerStockDTO.setWebsitName(partsNewRefundManage.getReceiveWebsitName());
                workerStockDTO.setPartsWebsitId(partsNewRefundManage.getReceivePartsWebsitId());
                workerStockDTO.setSdate(DateUtil.date());
                workerStockDTO.setGoodsType(WebsitGoodsTypeEnum.P.toString());
                workerStockDTO.setGoodsId(refundManageItem.getPartsNumber());
                workerStockDTO.setGoodsName(refundManageItem.getPartsName());
                workerStockDTO.setMaterialGroupName(refundManageItem.getMaterialGroupName());
                workerStockDTO.setGoodsStockUnit(refundManageItem.getGoodsStockUnit());
                workerStockDTO.setPrice(BigDecimal.ZERO);
                workerStockDTO.setRef(partsNewRefundManage.getApplyNo());
                workerStockDTO.setRefType(PartsRefTypeEnum.NEW_REFUND.getRemark());
                workerStockDTO.setPartsAttr(partsAttr1);
                workerStockDTO.setChangeQty(refundManageItem.getQty());
                workerStockDTO.setDirectFlag(DirectFlagEnum.SUB.getKey());
                workerStockDTO.setRemark(refundManageItem.getRemark());
                workerStockDTO.setOperateBy(operateBy);
                workerStockDTO.setOperateTime(operateTime);

                workerStockDTOList.add(workerStockDTO);
            }
            if (StringUtils.isNotBlank(partsAttr2)) {
                WorkerStockDTO workerStockDTO = new WorkerStockDTO();
                workerStockDTO.setCompanyWechatId(partsNewRefundManage.getCompanyWechatId());
                workerStockDTO.setCompanyWechatName(partsNewRefundManage.getCompanyWechatName());
                workerStockDTO.setIdentity(partsNewRefundManage.getIdentity());
                workerStockDTO.setWorkerId(partsNewRefundManage.getWorkerId());
                workerStockDTO.setWorkerName(partsNewRefundManage.getWorkerName());
                workerStockDTO.setWebsitId(partsNewRefundManage.getReceiveWebsitId());
                workerStockDTO.setWebsitName(partsNewRefundManage.getReceiveWebsitName());
                workerStockDTO.setPartsWebsitId(partsNewRefundManage.getReceivePartsWebsitId());
                workerStockDTO.setSdate(DateUtil.date());
                workerStockDTO.setGoodsType(WebsitGoodsTypeEnum.P.toString());
                workerStockDTO.setGoodsId(refundManageItem.getPartsNumber());
                workerStockDTO.setGoodsName(refundManageItem.getPartsName());
                workerStockDTO.setMaterialGroupName(refundManageItem.getMaterialGroupName());
                workerStockDTO.setGoodsStockUnit(refundManageItem.getGoodsStockUnit());
                workerStockDTO.setPrice(BigDecimal.ZERO);
                workerStockDTO.setRef(partsNewRefundManage.getApplyNo());
                workerStockDTO.setRefType(PartsRefTypeEnum.NEW_REFUND.getRemark());
                workerStockDTO.setPartsAttr(partsAttr2);
                workerStockDTO.setChangeQty(refundManageItem.getQty());
                workerStockDTO.setDirectFlag(DirectFlagEnum.ADD.getKey());
                workerStockDTO.setRemark(refundManageItem.getRemark());
                workerStockDTO.setOperateBy(operateBy);
                workerStockDTO.setOperateTime(operateTime);

                workerStockDTOList.add(workerStockDTO);
            }
        }

        return workerStockDTOList;
    }
}
