package com.fjhx.victoriatourist.service.quality.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.utils.Assert;
import com.fjhx.kd100.entity.company.po.CompanyInfo;
import com.fjhx.kd100.service.company.CompanyInfoService;
import com.fjhx.purchase.entity.purchase.po.Purchase;
import com.fjhx.purchase.service.purchase.PurchaseService;
import com.fjhx.supply.service.supplier.SupplierInfoService;
import com.fjhx.victoriatourist.entity.abnormal.po.AbnormalInfo;
import com.fjhx.victoriatourist.entity.quality.dto.QualityInfoDto;
import com.fjhx.victoriatourist.entity.quality.dto.QualityInfoSelectDto;
import com.fjhx.victoriatourist.entity.quality.po.QualityDetails;
import com.fjhx.victoriatourist.entity.quality.po.QualityInfo;
import com.fjhx.victoriatourist.entity.quality.vo.QualityInfoVo;
import com.fjhx.victoriatourist.mapper.quality.QualityInfoMapper;
import com.fjhx.victoriatourist.service.abnormal.AbnormalInfoService;
import com.fjhx.victoriatourist.service.quality.QualityDetailsService;
import com.fjhx.victoriatourist.service.quality.QualityInfoService;
import com.fjhx.wms.entity.arrival.po.ArrivalStockRecords;
import com.fjhx.wms.entity.arrival.po.ArrivalStockRecordsDetails;
import com.fjhx.wms.entity.stock.emums.JournalType;
import com.fjhx.wms.entity.stock.po.Stock;
import com.fjhx.wms.entity.stock.po.StockJournal;
import com.fjhx.wms.entity.stock.po.StockJournalDetails;
import com.fjhx.wms.entity.stock.po.StockWait;
import com.fjhx.wms.service.arrival.ArrivalStockRecordsDetailsService;
import com.fjhx.wms.service.arrival.ArrivalStockRecordsService;
import com.fjhx.wms.service.stock.StockJournalDetailsService;
import com.fjhx.wms.service.stock.StockJournalService;
import com.fjhx.wms.service.stock.StockService;
import com.fjhx.wms.service.stock.StockWaitService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


/**
 * <p>
 * 质检 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-26
 */
@Service
public class QualityInfoServiceImpl extends ServiceImpl<QualityInfoMapper, QualityInfo> implements QualityInfoService {
    @Autowired
    private SupplierInfoService supplierInfoService;
    @Autowired
    private CompanyInfoService companyInfoService;
    @Autowired
    private QualityDetailsService qualityDetailsService;
    @Autowired
    private StockService stockService;
    @Autowired
    private StockJournalService stockJournalService;
    @Autowired
    private StockJournalDetailsService stockJournalDetailsService;
    @Autowired
    private ArrivalStockRecordsDetailsService arrivalStockRecordsDetailsService;
    @Autowired
    private ArrivalStockRecordsService arrivalStockRecordsService;
    @Autowired
    private AbnormalInfoService abnormalInfoService;
    @Autowired
    private StockWaitService stockWaitService;
    @Autowired
    private PurchaseService purchaseService;

    @Override
    public Page<QualityInfoVo> getPage(QualityInfoSelectDto dto) {
        IWrapper<QualityInfo> wrapper = getWrapper();
        wrapper.orderByDesc("qi", QualityInfo::getId);
        Page<QualityInfoVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        return page;
    }

    /**
     * 维多利亚获取已入库待质检分页
     */
    @Override
    public Page<QualityInfoVo> getPage1(QualityInfoSelectDto dto) {
        IWrapper<QualityInfo> wrapper = getWrapper();
        wrapper.orderByDesc("asr", QualityInfo::getId);
        wrapper.eq("asr", QualityInfoVo::getQualityStatus, dto.getQualityStatus());
        Page<QualityInfoVo> page = this.baseMapper.getPage1(dto.getPage(), wrapper);
        List<QualityInfoVo> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return page;
        }
        //赋值供应商名称
        supplierInfoService.attributeAssign(records, QualityInfoVo::getSupplyId, (item, supplier) -> {
            item.setSupplyName(supplier.getName());
        });
        //赋值物流公司名称
        List<String> logisticsCompanyCodes = records.stream().map(QualityInfoVo::getLogisticsCompanyCode).distinct()
                .filter(ObjectUtil::isNotNull).collect(Collectors.toList());
        if (ObjectUtil.isEmpty(logisticsCompanyCodes)) {
            return page;
        }
        Map<String, String> stringStringMap = companyInfoService.mapKV(CompanyInfo::getCode, CompanyInfo::getName,
                q -> q.in(CompanyInfo::getCode, logisticsCompanyCodes));
        records.forEach(item -> item.setLogisticsCompanyName(stringStringMap.get(item.getLogisticsCompanyCode())));
        //赋值采购员名称
        UserUtil.assignmentNickName(records, QualityInfoVo::getPurchaseUserId, QualityInfoVo::setPurchaseUserName);
        return page;
    }

    @Override
    public QualityInfoVo detail(Long id) {
        QualityInfo QualityInfo = this.getById(id);
        QualityInfoVo result = BeanUtil.toBean(QualityInfo, QualityInfoVo.class);
        return result;
    }

    @DSTransactional
    @Override
    public void add(QualityInfoDto qualityInfoDto) {
        qualityInfoDto.setId(IdWorker.getId());

        qualityInfoDto.setType(1);//设置为到货质检
        qualityInfoDto.setStatus(2);//部分质检
        ArrivalStockRecords arrivalStockRecords = arrivalStockRecordsService.getById(qualityInfoDto.getArrivalStockRecordsId());
        Assert.notEmpty(arrivalStockRecords,"查询不到到货信息");
        arrivalStockRecords.setQualityStatus(2);//质检完成

        //根据到货编号生成质检编号
        Integer codeNum = 0;
        String itemPrefix = arrivalStockRecords.getArrivalCode();
        QualityInfo qualityInfo = this.query()
                .likeRight("code", itemPrefix).
                orderByDesc("code").last("limit 1")
                .one();
        if (ObjectUtil.isNotEmpty(qualityInfo)) {
            codeNum = Convert.toInt(qualityInfo.getCode().substring(itemPrefix.length() + 1));
        }
        String code = String.format("%s-%0" + 3 + "d", itemPrefix, codeNum + 1);
        qualityInfoDto.setCode(code);

        qualityInfoDto.setWarehouseId(arrivalStockRecords.getWarehouseId());
        //查询入库明细
        List<ArrivalStockRecordsDetails> arrivalStockRecordsDetailsList = arrivalStockRecordsDetailsService.list(q -> q.eq(ArrivalStockRecordsDetails::getArrivalStockRecordsId, qualityInfoDto.getArrivalStockRecordsId()));
        Map<Long, ArrivalStockRecordsDetails> arrivalStockRecordsDetailsMap = arrivalStockRecordsDetailsList.stream().collect(Collectors.toMap(ArrivalStockRecordsDetails::getId, Function.identity()));
        //创建质检记录
        qualityInfoDto.setBussinessId(qualityInfoDto.getArrivalStockRecordsId());
        //创建质检明细
        List<QualityDetails> qualityDetailsList = qualityInfoDto.getQualityDetailsList();
        int qFlag = 0;//质检存在不合格标志
        for (QualityDetails qualityDetails : qualityDetailsList) {
            qualityDetails.setId(null);//将明细id置空解决前端误传
            qualityDetails.setQualityInfoId(qualityInfoDto.getId());
            ArrivalStockRecordsDetails arrivalStockRecordsDetails = arrivalStockRecordsDetailsMap.get(qualityDetails.getArrivalStockRecordsDetailsId());
            if (ObjectUtil.isEmpty(arrivalStockRecordsDetails)) {
                throw new ServiceException("查询不到到货明细信息");
            }
            BigDecimal quantity = arrivalStockRecordsDetails.getQuantity();
            qualityDetails.setTotalQuantity(quantity);

            BigDecimal count = qualityDetails.getQualifiedQuantity().add(qualityDetails.getDisqualificationQuantity());
            //统计已经质检的数量
            BigDecimal qualityQuantity = arrivalStockRecordsDetails.getQualityQuantity();
            qualityQuantity = ObjectUtil.isEmpty(qualityQuantity) ? BigDecimal.ZERO : qualityQuantity;
            arrivalStockRecordsDetails.setQualityQuantity(qualityQuantity.add(count));
            if (quantity.compareTo(arrivalStockRecordsDetails.getQualityQuantity()) > 0) {
                qualityInfoDto.setStatus(1);//修改为部分质检
                arrivalStockRecords.setQualityStatus(1);//修改为部分质检
            }

            //存在质检不合格创建异常
            if (qualityDetails.getDisqualificationQuantity().compareTo(BigDecimal.ZERO) != 0) {
                qFlag++;
            }
        }

        this.save(qualityInfoDto);

        if (qFlag != 0) {
            AbnormalInfo abnormalInfo = new AbnormalInfo();
            abnormalInfo.setStatus(0);
            abnormalInfo.setId(IdWorker.getId());
            abnormalInfo.setType(10);
//            abnormalInfo.setLinkId(qualityInfoDto.getId());
//            abnormalInfo.setLinkCode(qualityInfoDto.getCode());
            //将异常关联详细设置成采购id和采购单号
            StockWait stockWait = stockWaitService.getById(arrivalStockRecords.getStockWaitId());
            Assert.notEmpty(stockWait,"查询不到待入库信息");
            Purchase purchase = purchaseService.getById(stockWait.getBusinessId());
            Assert.notEmpty(purchase,"查询不到采购信息");
            String victoriatouristJson = purchase.getVictoriatouristJson();
            JSONObject json = ObjectUtil.isNotEmpty(victoriatouristJson) ? JSONObject.parseObject(victoriatouristJson) : new JSONObject();
            //赋值关联信息
            abnormalInfo.setLinkId(purchase.getId());
            abnormalInfo.setLinkCode(json.getString("contractCode"));

            abnormalInfo.setTitle("质检存在不合格");
            abnormalInfoService.save(abnormalInfo);
        }

        arrivalStockRecordsService.updateById(arrivalStockRecords);
        arrivalStockRecordsDetailsService.updateBatchById(arrivalStockRecordsDetailsList);

        qualityDetailsService.saveBatch(qualityDetailsList);
        //操作库存
        //创建出入库记录
        StockJournal stockJournal = new StockJournal();
        stockJournal.setType(JournalType.ARRIVAL_QUALITY.getDetailType());
        stockJournal.setOpType(1);//入库;
        stockJournal.setBusinessId(qualityInfoDto.getId());
        stockJournal.setWarehouseId(arrivalStockRecords.getWarehouseId());
        stockJournalService.save(stockJournal);
        List<StockJournalDetails> stockJournalDetailsList = new ArrayList<>();

        List<Stock> stockList = new ArrayList<>();
        for (QualityDetails qualityDetails : qualityDetailsList) {
            Stock stock = stockService.getOne(q -> q.eq(Stock::getProductId, qualityDetails.getProductInfoId()).eq(Stock::getWarehouseId, qualityInfoDto.getWarehouseId()));
            if (ObjectUtil.isEmpty(stock)) {
                stock = new Stock();
                stock.setProductId(qualityDetails.getProductInfoId());
                stock.setWarehouseId(arrivalStockRecords.getWarehouseId());
                stock.setQuantity(BigDecimal.ZERO);
            }
            String victoriatouristJson = stock.getVictoriatouristJson();
            JSONObject json = ObjectUtil.isEmpty(victoriatouristJson) ? new JSONObject() : JSONObject.parseObject(victoriatouristJson);

            BigDecimal defectiveQuantity = json.getBigDecimal("defectiveQuantity");//次品库存
            defectiveQuantity = ObjectUtil.isEmpty(defectiveQuantity) ? BigDecimal.ZERO : defectiveQuantity;

            BigDecimal frozenQuantity = json.getBigDecimal("frozenQuantity");//冻结库存
            frozenQuantity = ObjectUtil.isEmpty(frozenQuantity) ? BigDecimal.ZERO : frozenQuantity;

            //质检合格增加可用库存
            stock.setQuantity(stock.getQuantity().add(qualityDetails.getQualifiedQuantity()));
            //质检不合格增加次品库存
            defectiveQuantity = defectiveQuantity.add(qualityDetails.getDisqualificationQuantity());
            json.put("defectiveQuantity", defectiveQuantity);
            //减少冻结库存
            BigDecimal count = qualityDetails.getQualifiedQuantity().add(qualityDetails.getDisqualificationQuantity());
            frozenQuantity = frozenQuantity.subtract(count);
            if (frozenQuantity.compareTo(BigDecimal.ZERO) < 0) {
                throw new ServiceException("冻结库存不足");
            }
            json.put("frozenQuantity", frozenQuantity);

            stock.setVictoriatouristJson(JSONObject.toJSONString(json,JSONWriter.Feature.WriteLongAsString));
            stockList.add(stock);

            StockJournalDetails stockJournalDetails = new StockJournalDetails();
            stockJournalDetails.setStockJournalId(stockJournal.getId());
            stockJournalDetails.setProductId(qualityDetails.getProductInfoId());
            stockJournalDetails.setQuantity(qualityDetails.getQualifiedQuantity().add(qualityDetails.getDisqualificationQuantity()));
            stockJournalDetails.setBusinessDetailsId(qualityDetails.getId());
            stockJournalDetailsList.add(stockJournalDetails);
        }
        stockService.saveOrUpdateBatch(stockList);
        stockJournalDetailsService.saveBatch(stockJournalDetailsList);
    }

    @Override
    public void edit(QualityInfoDto qualityInfoDto) {
        this.updateById(qualityInfoDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

}
