package com.fjhx.stock.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.entity.stock.StockCheckrecord;
import com.fjhx.entity.stock.StockCheckrecorddetail;
import com.fjhx.entity.stock.StockDetail;
import com.fjhx.entity.stock.StockTag;
import com.fjhx.listener.WebSocketEventListener;
import com.fjhx.service.WebSocketServer;
import com.fjhx.stock.mapper.StockCheckrecordMapper;
import com.fjhx.stock.service.StockCheckrecordService;
import com.fjhx.stock.service.StockCheckrecorddetailService;
import com.fjhx.stock.service.StockDetailService;
import com.fjhx.stock.service.StockTagService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * <p>
 * 盘点记录 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-12-05
 */
@Service
@Slf4j
public class StockCheckrecordServiceImpl extends ServiceImpl<StockCheckrecordMapper, StockCheckrecord> implements StockCheckrecordService {

    /**
     * 记录盘点数据
     * key：仓库id
     * value：rfidList
     */
    public static final Map<String, List<String>> map = new ConcurrentHashMap<>();

    @Autowired
    private StockDetailService stockDetailService;

    @Autowired
    private StockTagService stockTagService;

    @Autowired
    private StockCheckrecorddetailService stockCheckrecorddetailService;

    @Override
    public void checkStart(String instructions, String stockHouseId) {
        JSONObject data = new JSONObject();
        // 盘点指令
        data.put("instructions", instructions);
        // 开启rfid扫描type
        data.put("type", "2");
        // 盘点业务类型
        data.put("businessType", "3");
        // 盘点仓库id  一楼仓库'c185883dba22478cb593d33f6b66cc53' 四楼仓库'0b8f584250bb4b40b72d641ce4849d15'
        data.put("stockHouseId", stockHouseId);

        // 创建记录rfid的list
        map.put(stockHouseId, Collections.synchronizedList(new ArrayList<>()));

        // 开启扫描
        WebSocketServer.sendInfo(WebSocketEventListener.WEB_STOCK_PROGRAM, WebSocketEventListener.OPERATING_UPPER_COMPUTER, data);
    }

    @Override
    public void checkCallBack(JSONObject data) {

        String stockHouseId = data.getString("stockHouseId");
        String rfid = data.getString("rfid");

        map.get(stockHouseId).add(rfid);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void checkEnd(String instructions, String stockHouseId) {
        Date date = new Date();

        JSONObject data = new JSONObject();
        // 盘点指令
        data.put("instructions", instructions);
        // 关闭rfid扫描type
        data.put("type", "9");
        // 关闭扫描
        WebSocketServer.sendInfo(WebSocketEventListener.WEB_STOCK_PROGRAM, WebSocketEventListener.OPERATING_UPPER_COMPUTER, data);

        // 盘点到的rfid
        List<String> rfidList = map.remove(stockHouseId);

        ArrayList<String> copyRfidList = new ArrayList<>(rfidList);
        List<String> excludeRfidCodeList = new ArrayList<>();

        if (rfidList.size() > 0) {
            List<Map<String, Object>> list = stockDetailService.listMaps(Wrappers.<StockDetail>query()
                    .ge("ExpiredDt", date)
                    .select("RfidCode rfidCode")
            );

            excludeRfidCodeList = list.stream().map(item -> Convert.toStr(item.get("rfidCode"))).collect(Collectors.toList());

            for (Map<String, Object> map : list) {
                rfidList.remove(Convert.toStr(map.get("rfidCode")));
            }
        }

        log.error("\r\n盘点结束：\r\n扫描仓库：{}\r\n扫描到的rfid：{},\r\n排除的rfid：{},\r\n排除之后的rfid：{}",
                stockHouseId.equals("c185883dba22478cb593d33f6b66cc53") ? "一楼仓库" : "四楼仓库",
                JSONObject.toJSONString(copyRfidList),
                JSONObject.toJSONString(excludeRfidCodeList),
                rfidList
        );

        // 添加盘点记录
        StockCheckrecord stockCheckrecord = new StockCheckrecord();
        stockCheckrecord.setIsDelete(0);
        stockCheckrecord.setCreatedTime(date);
        stockCheckrecord.setUpdatedTime(date);
        stockCheckrecord.setStockCheckResult(0);
        stockCheckrecord.setType(3);
        stockCheckrecord.setStockHouseId(stockHouseId);
        stockCheckrecord.setApproveBillState(0);
        stockCheckrecord.setCheckState(0);
        stockCheckrecord.setPeopleCheckResut(1);
        save(stockCheckrecord);

        String recordId = stockCheckrecord.getId();

        // 获取所有在库物料
        List<Map<String, Object>> stockList = stockDetailService.listMaps(Wrappers.<StockDetail>query()
                .select(
                        "count(id) count", // 库存卷数
                        "MaterialCode materialCode", // 对应物料编码
                        "sum(Quantity) quantity" // 库存数量
                )
                .eq("StockHouseId", stockHouseId) // 对应仓库id
                .lt("ExpiredDt", date) // 排除确认在库的标签
                .eq("IsDelete", "0") // 未删除
                .groupBy("MaterialCode") // 物料编码分组
        );

        List<Map<String, Object>> checkList;

        if (rfidList.size() == 0) {
            checkList = new ArrayList<>();
        } else {
            // 扫描出的rfid数量
            checkList = stockTagService.listMaps(Wrappers.<StockTag>query()
                    .select(
                            "count(id) count", // 盘点卷数
                            "MaterialCode materialCode", // 对应物料编码
                            "sum(Quantity) quantity" // 盘点数量
                    )
                    .eq("IsDelete", 0) // 未删除
                    .in("RfidCode", rfidList) // 扫描出的rfid
                    .groupBy("MaterialCode") // 物料编码分组
            );
        }

        // 记录异常物料
        List<StockCheckrecorddetail> list = new ArrayList<>();

        // 库存信息按物料编码转map
        Map<String, Map<String, Object>> stockMap = stockList.stream().collect(Collectors.toMap(
                item -> item.get("materialCode").toString(),
                item -> item
        ));

        // 循环扫描出的RFID
        for (Map<String, Object> map : checkList) {
            // 物料编码
            String materialCode = map.get("materialCode").toString();
            // 扫描卷数
            Integer count = Convert.toInt(map.get("count"), 0);
            // 扫描数量
            BigDecimal quantity = Convert.toBigDecimal(map.get("quantity"), BigDecimal.ZERO);

            // 获取此物料库存信息，并删除map中的物料信息
            Map<String, Object> stock = stockMap.remove(materialCode);

            // 无库存信息
            if (stock == null) {
                // 添加异常，扫描出rfid，但库存没有
//                list.add(createStockCheckrecorddetail(
//                        date, recordId, stockHouseId, materialCode, BigDecimal.ZERO, quantity, 0, count));
            } else {
                // 库存卷数
                int stockCount = Convert.toInt(stock.get("count"), 0);
                // 库存数量
                BigDecimal stockQuantity = Convert.toBigDecimal(stock.get("quantity"), BigDecimal.ZERO);

                // 库存卷数大于扫描卷数
                if (stockCount > count) {
                    list.add(createStockCheckrecorddetail(
                            date, recordId, stockHouseId, materialCode, stockQuantity, quantity, stockCount, count));
                }

            }
        }

        // 如果map还有值，表示没扫描出这个物料，但库存中有这个物料
        if (stockMap.size() > 0) {
            stockMap.forEach((k, v) -> {
                // 物料编码
                String materialCode = v.get("materialCode").toString();
                // 库存卷数
                int stockCount = Convert.toInt(v.get("count"), 0);
                // 库存数量
                BigDecimal stockQuantity = Convert.toBigDecimal(v.get("quantity"), BigDecimal.ZERO);

                list.add(createStockCheckrecorddetail(
                        date, recordId, stockHouseId, materialCode, stockQuantity, BigDecimal.ZERO, stockCount, 0));

            });
        }

        // 添加异常物料信息
        stockCheckrecorddetailService.saveBatch(list);
    }

    /**
     * @param date              完成时间
     * @param recordId          盘点主表id
     * @param stockHouseId      仓库id
     * @param materialCode      物料编码
     * @param quantity          库存数量
     * @param allStockScanQty   盘点数量
     * @param TagQuantity       库存卷数
     * @param AllStockScanCount 盘点卷数
     */
    private StockCheckrecorddetail createStockCheckrecorddetail(
            Date date, String recordId, String stockHouseId, String materialCode, BigDecimal quantity,
            BigDecimal allStockScanQty, Integer TagQuantity, Integer AllStockScanCount) {

        StockCheckrecorddetail stockCheckrecorddetail = new StockCheckrecorddetail();
        stockCheckrecorddetail.setIsDelete(0);
        stockCheckrecorddetail.setCreatedTime(date);
        stockCheckrecorddetail.setUpdatedTime(date);
        stockCheckrecorddetail.setRecordId(recordId);
        stockCheckrecorddetail.setHandTagCount(0);
        stockCheckrecorddetail.setCheckTagCount(0);
        stockCheckrecorddetail.setIsCompleteCheck(0);
        stockCheckrecorddetail.setApproveBillState(0);
        stockCheckrecorddetail.setStockHouseId(stockHouseId);
        stockCheckrecorddetail.setCheckQty(BigDecimal.ZERO);
        stockCheckrecorddetail.setPlaceAreaId("");

        stockCheckrecorddetail.setMaterialCode(materialCode);
        stockCheckrecorddetail.setQuantity(quantity);
        stockCheckrecorddetail.setAllStockScanQty(allStockScanQty);
        stockCheckrecorddetail.setTagQuantity(TagQuantity);
        stockCheckrecorddetail.setAllStockScanCount(AllStockScanCount);

        return stockCheckrecorddetail;
    }


}
