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

import cn.hutool.core.bean.BeanUtil;
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.material.stock.WebsitStockDTO;
import com.gree.mall.manager.bean.material.stock.WorkerStockDTO;
import com.gree.mall.manager.bean.material.worker.NewRefundManageBean;
import com.gree.mall.manager.bean.material.worker.NewRefundManageItemBean;
import com.gree.mall.manager.bean.material.worker.NewRefundManageRecordBean;
import com.gree.mall.manager.bean.material.worker.NewRefundManageVO;
import com.gree.mall.manager.commonmapper.MaterialMapper;
import com.gree.mall.manager.enums.IsEnum;
import com.gree.mall.manager.enums.base.BaseEnum;
import com.gree.mall.manager.enums.material.*;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.logic.material.stock.MaterialGoodsStockLogic;
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.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
@RequiredArgsConstructor
public class NewRefundManageLogic {

    private final CommonLogic commonLogic;
    private final MaterialMapper materialMapper;
    private final WebsitPartsNewRefundManageService websitPartsNewRefundManageService;
    private final WebsitPartsNewRefundManageItemService websitPartsNewRefundManageItemService;
    private final WebsitPartsNewRefundManageRecordService websitPartsNewRefundManageRecordService;
    private final MaterialGoodsStockLogic materialGoodsStockLogic;
    private final WebsitPartsRefundRecordService websitPartsRefundRecordService;
    private final StorageService storageService;

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

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

    public NewRefundManageBean detail(String applyNo) {
        final WebsitPartsNewRefundManage manage = websitPartsNewRefundManageService.getById(applyNo);
        NewRefundManageBean bean = new NewRefundManageBean();
        BeanUtils.copyProperties(manage, bean);

        final List<WebsitPartsNewRefundManageItem> items = websitPartsNewRefundManageItemService.lambdaQuery()
                .eq(WebsitPartsNewRefundManageItem::getApplyNo, applyNo)
                .list();

        final List<WebsitPartsNewRefundManageRecord> records = websitPartsNewRefundManageRecordService.lambdaQuery()
                .eq(WebsitPartsNewRefundManageRecord::getApplyNo, applyNo)
                .list();

        bean.setNewRefundManageItemBeanList(BeanUtil.copyToList(items, NewRefundManageItemBean.class));
        bean.setPartsNewRefundManageRecordList(BeanUtil.copyToList(records, NewRefundManageRecordBean.class));

        return bean;
    }

    @Transactional
    public void examine(String applyNo, String flag, String examineRemark) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        WebsitPartsNewRefundManage partsNewRefundManage = websitPartsNewRefundManageService.getById(applyNo);
        if (!partsNewRefundManage.getFlag().equals(PartsOrderFlagEnum.SUBMIT.getKey())) {
            throw new RemoteServiceException(applyNo + "单据状态："
                    + BaseEnum.keyToValue(PartsOrderFlagEnum.class, partsNewRefundManage.getFlag()) + "，审批失败");
        }
        DateTime curDate = DateUtil.date();
        partsNewRefundManage.setFlag(flag)
                .setExamineRemark(examineRemark)
                .setExamineBy(adminUser.getNickName())
                .setExamineTime(curDate)
                .updateById();
        if (flag.equals(PartsOrderFlagEnum.AGREE.toString())) {
            // 通过
//            this.insertPartsMessageTip(partsNewRefundManage, curDate);
        }else if (flag.equals(PartsOrderFlagEnum.REJECT.toString())) {
            // 驳回
            List<WebsitPartsNewRefundManageItem> partsNewRefundManageItems = websitPartsNewRefundManageItemService.lambdaQuery()
                    .eq(WebsitPartsNewRefundManageItem::getApplyNo, partsNewRefundManage.getApplyNo())
                    .list();
            List<WebsitPartsNewRefundManageRecord> partsNewRefundManageRecordList = websitPartsNewRefundManageRecordService.lambdaQuery()
                    .eq(WebsitPartsNewRefundManageRecord::getApplyNo, partsNewRefundManage.getApplyNo())
                    .list();
            // 驳回状态时临占新件库存减 新件库存加
            List<WorkerStockDTO> workerStockDTOList = this.createWorkerStockDTO(partsNewRefundManage, partsNewRefundManageItems,
                    partsNewRefundManage.getExamineBy(), partsNewRefundManage.getExamineTime(),
                    PartsAttrEnum.TEMP_NEW.getKey(), PartsAttrEnum.NEW.getKey());
            materialGoodsStockLogic.handleWorkerStock(workerStockDTOList);
            // 驳回状态时销售明细还原数量
            materialGoodsStockLogic.revertNewPartsSalesQty(partsNewRefundManage.getCompanyWechatId(), partsNewRefundManage.getReceiveWebsitId(), partsNewRefundManage.getReceivePartsWebsitId(),
                    partsNewRefundManage.getIdentity(), partsNewRefundManageRecordList);
        }
    }

    @Transactional
    public void refund(String applyNo) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        WebsitPartsNewRefundManage partsNewRefundManage = websitPartsNewRefundManageService.getById(applyNo);
        if (!partsNewRefundManage.getFlag().equals(PartsOrderFlagEnum.AGREE.getKey())) {
            throw new RemoteServiceException(applyNo + "单据状态："
                    + BaseEnum.keyToValue(PartsOrderFlagEnum.class, partsNewRefundManage.getFlag()) + "，归还失败");
        }

        partsNewRefundManage.setFlag(PartsOrderFlagEnum.REFUNDED.getKey())
                .setRefundedBy(adminUser.getNickName())
                .setRefundedTime(DateUtil.date())
                .updateById();

        // 减师傅临占新件库存
        List<WebsitPartsNewRefundManageItem> partsNewRefundManageItems = websitPartsNewRefundManageItemService.lambdaQuery()
                .eq(WebsitPartsNewRefundManageItem::getApplyNo, partsNewRefundManage.getApplyNo())
                .list();
        List<WorkerStockDTO> workerStockDTOList = this.createWorkerStockDTO(partsNewRefundManage, partsNewRefundManageItems,
                partsNewRefundManage.getRefundedBy(), partsNewRefundManage.getRefundedTime(),
                PartsAttrEnum.TEMP_NEW.getKey(), null);
        materialGoodsStockLogic.handleWorkerStock(workerStockDTOList);

        // 增加网点新件库存
        List<WebsitStockDTO> shopStockDTOList = this.createWebsitStockDTO(partsNewRefundManage, partsNewRefundManageItems);
        materialGoodsStockLogic.handleWebsitStock(shopStockDTOList);

        //TODO 插入退款记录
        List<WebsitPartsNewRefundManageRecord> partsNewRefundManageRecords = websitPartsNewRefundManageRecordService.lambdaQuery()
                .eq(WebsitPartsNewRefundManageRecord::getApplyNo, partsNewRefundManage.getApplyNo())
                .list();
        List<WebsitPartsRefundRecord> partsRefundRecordList = this.createRefundRecord(partsNewRefundManage, partsNewRefundManageRecords);
        if(CollectionUtil.isNotEmpty(partsRefundRecordList))
            websitPartsRefundRecordService.saveBatch(partsRefundRecordList);
    }

    private List<WebsitPartsRefundRecord> createRefundRecord(WebsitPartsNewRefundManage partsNewRefundManage, List<WebsitPartsNewRefundManageRecord> partsNewRefundManageRecords) {
        List<WebsitPartsRefundRecord> partsRefundRecordList = new ArrayList<>();
        for (WebsitPartsNewRefundManageRecord partsNewRefundManageRecord : partsNewRefundManageRecords) {
            if (Objects.isNull(partsNewRefundManageRecord.getRefundAmountMode())
                    || partsNewRefundManageRecord.getRefundAmountMode().equals(PayTypeEnum.CASH.getKey())) {
                continue;
            }
            WebsitPartsRefundRecord partsRefundRecord = new WebsitPartsRefundRecord();
            partsRefundRecord.setRefundNo(IdWorker.getIdStr())
                    .setCompanyWechatId(partsNewRefundManage.getCompanyWechatId())
                    .setCompanyWechatName(partsNewRefundManage.getCompanyWechatName())
                    .setRecordId(partsNewRefundManageRecord.getId())
                    .setWebsitId(partsNewRefundManage.getReceiveWebsitId())
                    .setWebsitName(partsNewRefundManage.getReceiveWebsitName())
                    .setPartsWebsitId(partsNewRefundManage.getReceivePartsWebsitId())
                    .setIdentity(partsNewRefundManage.getIdentity())
                    .setWorkerId(partsNewRefundManage.getWorkerId())
                    .setWorkerName(partsNewRefundManage.getWorkerName())
                    .setSalesId(partsNewRefundManageRecord.getSalesId())
                    .setSalesItemId(partsNewRefundManageRecord.getSalesItemId())
                    .setRef(partsNewRefundManage.getApplyNo())
                    .setRefType(PartsRefTypeEnum.NEW_REFUND.getKey())
                    .setPartsNumber(partsNewRefundManageRecord.getPartsNumber())
                    .setPartsName(partsNewRefundManageRecord.getPartsName())
                    .setRefundAmount(partsNewRefundManageRecord.getRefundAmount())
                    .setRefundState(PartsRefundStateEnum.WAIT.getKey())
                    .setIsExec(IsEnum.N.getValue())
                    .setCreateTime(DateUtil.date());
            partsRefundRecordList.add(partsRefundRecord);
        }
        return partsRefundRecordList;
    }

    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.getKey());
                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.getKey());
                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;
    }

    private List<WebsitStockDTO> createWebsitStockDTO(WebsitPartsNewRefundManage partsNewRefundManage, List<WebsitPartsNewRefundManageItem> partsNewRefundManageItems) {
        List<WebsitStockDTO> shopStockDTOList = new ArrayList<>();
        final Storage storage = storageService.lambdaQuery()
                .eq(Storage::getCompanyWechatId, partsNewRefundManage.getCompanyWechatId())
                .in(Storage::getWebsitId, partsNewRefundManage.getReceiveWebsitId())
                .eq(Storage::getIsDefault, IsEnum.Y.getValue())
                .one();

        for (WebsitPartsNewRefundManageItem partsNewRefundManageItem : partsNewRefundManageItems) {
            WebsitStockDTO websitStockDTO = new WebsitStockDTO();
            websitStockDTO.setCompanyWechatId(partsNewRefundManage.getCompanyWechatId());
            websitStockDTO.setCompanyWechatName(partsNewRefundManage.getCompanyWechatName());
            websitStockDTO.setWebsitId(partsNewRefundManage.getReceiveWebsitId());
            websitStockDTO.setWebsitName(partsNewRefundManage.getReceiveWebsitName());
            websitStockDTO.setSdate(partsNewRefundManage.getRefundedTime());
            websitStockDTO.setPartsWebsitId(partsNewRefundManage.getReceivePartsWebsitId());
            websitStockDTO.setGoodsType(WebsitGoodsTypeEnum.P.getKey());
            websitStockDTO.setGoodsId(partsNewRefundManageItem.getPartsNumber());
            websitStockDTO.setGoodsName(partsNewRefundManageItem.getPartsName());
            websitStockDTO.setPrice(BigDecimal.ZERO);
            websitStockDTO.setMaterialGroupName(partsNewRefundManageItem.getMaterialGroupName());
            websitStockDTO.setGoodsStockUnit(partsNewRefundManageItem.getGoodsStockUnit());
            websitStockDTO.setVoucherNo(partsNewRefundManage.getApplyNo());
            websitStockDTO.setRef(partsNewRefundManage.getApplyNo());
            websitStockDTO.setRefType(PartsRefTypeEnum.NEW_REFUND.getRemark());
            websitStockDTO.setApplyNo(partsNewRefundManage.getApplyNo());
            websitStockDTO.setObj(BaseEnum.keyToEnumNotNull(PartsRefundApplyTypeEnum.class, partsNewRefundManage.getApplyType()).getRemark());
            websitStockDTO.setPartsAttr(PartsAttrEnum.NEW.toString());
            websitStockDTO.setChangeQty(partsNewRefundManageItem.getQty());
            websitStockDTO.setDirectFlag(DirectFlagEnum.ADD.getKey());
            websitStockDTO.setRemark(partsNewRefundManageItem.getRemark());
            websitStockDTO.setOperateBy(partsNewRefundManage.getRefundedBy());
            websitStockDTO.setOperateTime(partsNewRefundManage.getRefundedTime());
            websitStockDTO.setStorageId(storage.getStorageId());
            shopStockDTOList.add(websitStockDTO);
        }
        return shopStockDTOList;
    }
}
