package com.fjhx.stock.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
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.entity.test.TestScan;
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 com.fjhx.test.service.TestScanService;
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 {

    @Autowired
    private TestScanService testScanService;

    /**
     * 记录盘点数据
     * 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, Long checkForwardSessionId, 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);
        data.put("forwardSessionId", checkForwardSessionId);
        data.put("forwardUserId", instructions);

        // 创建记录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 rfid = data.getString("rfid");

        if ("true".equals(data.getString("testFlag"))) {
            TestScan testScan = new TestScan();
            testScan.setRfid(rfid);
            testScan.setBatchFlag(data.getLong("forwardSessionId"));
            testScan.setScanTime(new Date());
            testScanService.save(testScan);
            return;
        }

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

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

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

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

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

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

        // 默认在库rfid
        // List<Map<String, Object>> inHouseMaterialCodeList = stockDetailService.listMaps(Wrappers.<StockDetail>query()
        //         .select("MaterialCode materialCode")
        //         .eq("IsDelete", 0)
        //         .eq("StockHouseId", stockHouseId)
        //         .ge("ExpiredDt", new Date())
        // );
        //
        // List<String> materialCodeList = inHouseMaterialCodeList.stream()
        //         .map(item -> Convert.toStr(item.get("materialCode"))).distinct().collect(Collectors.toList());
        //
        // if (materialCodeList.size() > 0) {
        //
        //     List<Map<String, Object>> inHouseList = stockDetailService.listMaps(Wrappers.<StockDetail>query()
        //             .select("RfidCode rfidCode")
        //             .eq("IsDelete", 0)
        //             .eq("StockHouseId", stockHouseId)
        //             .in("MaterialCode", materialCodeList)
        //     );
        //
        //     for (Map<String, Object> map : inHouseList) {
        //         String rfidCode = Convert.toStr(map.get("rfidCode"));
        //         if (!rfidList.contains(rfidCode)) {
        //             rfidList.add(rfidCode);
        //         }
        //     }
        //
        // }

        log.error("\r\n盘点结束：\r\n扫描仓库：{}\r\n扫描到的rfid：{},\r\n添加默认在库后的rfid：{}",
                (stockHouseId.equals("c185883dba22478cb593d33f6b66cc53") ? "一楼仓库：" : "四楼仓库：") + stockHouseId,
                JSONObject.toJSONString(copyRfidList),
                JSONObject.toJSONString(rfidList)
        );

        String recordId = IdWorker.getIdStr();

        // 获取所有在库物料
        List<Map<String, Object>> stockList = stockDetailService.listMaps(Wrappers.<StockDetail>query()
                .select(
                        "count(distinct rfidcode) count", // 库存卷数
                        "MaterialCode materialCode", // 对应物料编码
                        "sum(Quantity) quantity" // 库存数量
                )
                .eq("IsDelete", 0) // 未删除
                .eq("StockHouseId", stockHouseId) // 对应仓库id
                .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) {
                // 库存卷数
                int stockCount = Convert.toInt(stock.get("count"), 0);
                // 库存数量
                BigDecimal stockQuantity = Convert.toBigDecimal(stock.get("quantity"), BigDecimal.ZERO);

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

            }
        }

        // 如果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));

            });
        }


        // 添加盘点记录
        StockCheckrecord stockCheckrecord = new StockCheckrecord();
        stockCheckrecord.setId(recordId);
        stockCheckrecord.setIsDelete(0);
        stockCheckrecord.setCreatedTime(date);
        stockCheckrecord.setUpdatedTime(date);
        stockCheckrecord.setStockCheckResult(list.size() == 0 ? 1 : 0);
        stockCheckrecord.setType(3);
        stockCheckrecord.setStockHouseId(stockHouseId);
        stockCheckrecord.setApproveBillState(0);
        stockCheckrecord.setCheckState(0);
        stockCheckrecord.setPeopleCheckResut(1);
        save(stockCheckrecord);
        // 添加异常物料信息
        stockCheckrecorddetailService.saveBatch(list);
    }

    @Override
    public void testScanStart(String instructions, long flag, 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);
        data.put("forwardSessionId", flag);
        data.put("forwardUserId", instructions);
        // 测试标记
        data.put("testFlag", "true");

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

    @Override
    public void testScanEnd(String instructions, long flag, String stockHouseId) {
        JSONObject data = new JSONObject();
        // 盘点指令
        data.put("instructions", instructions);
        // 关闭rfid扫描type
        data.put("type", "9");
        data.put("forwardSessionId", flag);
        data.put("forwardUserId", instructions);
        // 关闭扫描
        WebSocketServer.sendInfo(WebSocketEventListener.WEB_STOCK_PROGRAM, WebSocketEventListener.OPERATING_UPPER_COMPUTER, data);
    }

    /**
     * @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;
    }


}
