package com.ruoyi.inventory.service.impl;

import java.util.*;

import cn.hutool.json.JSONUtil;
import com.ruoyi.asset.mapper.TbAssetInformationMapper;
import com.ruoyi.asset.mapper.TbLocationMapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.inventory.domain.TagInfo;
import com.ruoyi.inventory.domain.TbInventoryDetail;
import com.ruoyi.inventory.domain.dto.TakeStockDTO;
import com.ruoyi.inventory.domain.dto.TbAssetInventoryDTO;
import com.ruoyi.inventory.mapper.TbInventoryDetailMapper;
import com.ruoyi.utils.IDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.inventory.mapper.TbAssetInventoryMapper;
import com.ruoyi.inventory.domain.TbAssetInventory;
import com.ruoyi.inventory.service.ITbAssetInventoryService;

/**
 * 资产盘点记录Service业务层处理
 * 
 * @author ydl
 * @date 2023-06-01
 */
@Service
public class TbAssetInventoryServiceImpl implements ITbAssetInventoryService
{
    @Autowired
    private TbAssetInventoryMapper tbAssetInventoryMapper;

    @Autowired
    private TbAssetInformationMapper informationMapper;

    @Autowired
    private TbInventoryDetailMapper tbInventoryDetailMapper;

    @Autowired
    private TbLocationMapper locationMapper;

    /**
     * 查询资产盘点记录
     * 
     * @param id 资产盘点记录主键
     * @return 资产盘点记录
     */
    @Override
    public TbAssetInventory selectTbAssetInventoryById(Long id)
    {
        return tbAssetInventoryMapper.selectTbAssetInventoryById(id);
    }

    /**
     * 查询资产盘点记录列表
     * 
     * @param tbAssetInventory 资产盘点记录
     * @return 资产盘点记录
     */
    @Override
    public List<TbAssetInventory> selectTbAssetInventoryList(TbAssetInventory tbAssetInventory)
    {
        return tbAssetInventoryMapper.selectTbAssetInventoryList(tbAssetInventory);
    }

    /**
     * 新增资产盘点记录
     * 
     * @param tbAssetInventory 资产盘点记录
     * @return 结果
     */
    @Override
    public int insertTbAssetInventory(TbAssetInventory tbAssetInventory)
    {
        tbAssetInventory.setOrderNumber(IDUtil.getUUID1());
        return tbAssetInventoryMapper.insertTbAssetInventory(tbAssetInventory);
    }

    //手持机盘点
    @Override
    public int addByTakeStock(TakeStockDTO dto){
        //解析实体
        List<TagInfo> list = dto.getAssetList();
        String location = dto.getInventoryLocation();
        String orderNumber = dto.getOrderNumber();
        //提取epc
        ArrayList<String> epcList = new ArrayList<>();
        for (TagInfo tagInfo : list){
            epcList.add(tagInfo.getEpc());
        }
        //根据位置获取包含自身及子位置,递归
        List<String> locations = getNumberWithChildren(location);
        //获取所在位置内的资产
        List<String> rfidList = informationMapper.selectNumberByLocations(locations);
        //对比盘点
        List<String> intersection = new ArrayList<>(rfidList);
        intersection.retainAll(epcList);
        if (intersection.size()<rfidList.size()){
            //盘亏
            if (!orderNumber.isEmpty()){
                return takeStock(orderNumber, epcList, 2L);
            }else {
                return takeStock2(location, 2L, epcList);
            }
        }else if (list.size()>intersection.size()){
            //盘盈
            if (!orderNumber.isEmpty()){
                return takeStock(orderNumber, epcList, 1L);
            }else {
                return takeStock2(location, 1L, epcList);
            }
        }else if (intersection.size()==rfidList.size()){
            //正常
            if (!orderNumber.isEmpty()){
                return takeStock(orderNumber, epcList, 3L);
            }else {
                return takeStock2(location, 3L, epcList);
            }
        }else {
            return 0;
        }
    }

    /**
     * 修改资产盘点记录
     * 
     * @param tbAssetInventory 资产盘点记录
     * @return 结果
     */
    @Override
    public int updateTbAssetInventory(TbAssetInventory tbAssetInventory)
    {
        return tbAssetInventoryMapper.updateTbAssetInventory(tbAssetInventory);
    }

    /**
     * 批量删除资产盘点记录
     * 
     * @param ids 需要删除的资产盘点记录主键
     * @return 结果
     */
    @Override
    public int deleteTbAssetInventoryByIds(Long[] ids)
    {
        return tbAssetInventoryMapper.deleteTbAssetInventoryByIds(ids);
    }

    /**
     * 删除资产盘点记录信息
     * 
     * @param id 资产盘点记录主键
     * @return 结果
     */
    @Override
    public int deleteTbAssetInventoryById(Long id)
    {
        return tbAssetInventoryMapper.deleteTbAssetInventoryById(id);
    }

    @Override
    public List<TbAssetInventoryDTO> selectTbAssetInventoryDTOList(TbAssetInventoryDTO dto) {
        return tbAssetInventoryMapper.selectTbAssetInventoryDTOList(dto);
    }


    /**
     * 递归函数
     */
    public List<String> getNumberWithChildren(String number) {
        Set<String> result = new HashSet<>();
        Set<String> visited = new HashSet<>(); // 用于跟踪已访问过的节点

        processNumberWithChildren(number, result, visited); // 调用辅助方法处理节点及其子节点

        return new ArrayList<>(result);
    }

    private void processNumberWithChildren(String number, Set<String> result, Set<String> visited) {
        if (!visited.contains(number)) { // 避免重复处理节点
            visited.add(number);
            List<String> children = locationMapper.selectNumberByFather(number); // 调用mapper接口方法查询直接子节点

            // 递归处理每个子节点
            for (String child : children) {
                result.add(child);
                processNumberWithChildren(child, result, visited);
            }
        }
    }

    private int takeStock(String orderNumber, List<String> list, Long result){
        TbAssetInventory inventory = tbAssetInventoryMapper.selectTbAssetInventoryByNumber(orderNumber);
        if (inventory.getRecordStatus() == 1L) {
            inventory.setInventoryStatus(2L);
            inventory.setInventoryResult(result);
            //插入盘点明细
            TbInventoryDetail detail = new TbInventoryDetail();
            for (String number : list) {
                detail.setOrderNumber(orderNumber);
                detail.setInventoryMetadata(JSONUtil.toJsonStr(informationMapper.selectTbAssetInformationByAssetNumber(number)));
                tbInventoryDetailMapper.insertTbInventoryDetail(detail);
            }
            return updateTbAssetInventory(inventory);
        }else {
            return 0;
        }
    }

    private int takeStock2(String location, Long result, List<String> list){
        TbAssetInventory inventory = new TbAssetInventory();
        inventory.setInventoryStatus(2L);
        inventory.setInventoryResult(result);
        inventory.setRecordStatus(1L);
        inventory.setInventoryLocation(location);
        inventory.setInventoryDate(new Date());
        inventory.setName("线下自测");
        int i = insertTbAssetInventory(inventory);
        if(i < 1){
            throw new ServiceException("生成盘点记录失败");
        }
        String orderNumber = inventory.getOrderNumber();
        //插入盘点明细

        TbInventoryDetail detail = new TbInventoryDetail();
        for (String number : list) {
            detail.setOrderNumber(orderNumber);
            detail.setInventoryMetadata(JSONUtil.toJsonStr(informationMapper.selectTbAssetInformationByAssetNumber(number)));
            tbInventoryDetailMapper.insertTbInventoryDetail(detail);
        }
        return 1;
    }
}
