package com.ruoyi.asset.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.asset.domain.TbAssetBorrowRecord;
import com.ruoyi.asset.domain.TbAssetCategory;
import com.ruoyi.asset.domain.dto.TbAssetDTO;
import com.ruoyi.asset.domain.enums.TbAssetStatusEnum;
import com.ruoyi.asset.mapper.TbAssetBorrowRecordMapper;
import com.ruoyi.asset.mapper.TbAssetCategoryMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.UserUtils;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.asset.mapper.TbAssetMapper;
import com.ruoyi.asset.domain.TbAsset;
import com.ruoyi.asset.service.ITbAssetService;

import javax.annotation.Resource;

/**
 * 资产信息Service业务层处理
 * 
 * @author 原动力
 * @date 2023-03-27
 */
@Service
public class TbAssetServiceImpl extends ServiceImpl<TbAssetMapper, TbAsset> implements ITbAssetService
{
    @Autowired
    private TbAssetMapper tbAssetMapper;

    @Resource
    private SysDeptMapper sysDeptMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private TbAssetCategoryMapper tbAssetCategoryMapper;

    @Resource
    private TbAssetBorrowRecordMapper tbAssetBorrowRecordMapper;

    /**
     * 查询资产信息
     * 
     * @param id 资产信息主键
     * @return 资产信息
     */
    @Override
    public TbAsset selectTbAssetById(Long id)
    {
        return tbAssetMapper.selectTbAssetById(id);
    }

    /**
     * 查询资产信息列表
     * 
     * @param tbAsset 资产信息
     * @return 资产信息
     */
    @Override
    public List<TbAsset> selectTbAssetList(TbAsset tbAsset)
    {
        return tbAssetMapper.selectTbAssetList(tbAsset);
    }

    /**
     * 新增资产信息
     * 
     * @param tbAsset 资产信息
     * @return 结果
     */
    @Override
    public int insertTbAsset(TbAsset tbAsset)
    {
        return tbAssetMapper.insertTbAsset(tbAsset);
    }

    /**
     * 修改资产信息
     * 
     * @param tbAsset 资产信息
     * @return 结果
     */
    @Override
    public int updateTbAsset(TbAsset tbAsset)
    {
        return tbAssetMapper.updateTbAsset(tbAsset);
    }

    /**
     * 批量删除资产信息
     * 
     * @param ids 需要删除的资产信息主键
     * @return 结果
     */
    @Override
    public int deleteTbAssetByIds(Long[] ids)
    {
        return tbAssetMapper.deleteTbAssetByIds(ids);
    }

    /**
     * 删除资产信息信息
     * 
     * @param id 资产信息主键
     * @return 结果
     */
    @Override
    public int deleteTbAssetById(Long id)
    {
        return tbAssetMapper.deleteTbAssetById(id);
    }

    /**
     * 批量新增资产信息
     *
     * @param tbAssetList 资产信息集合
     * @return 结果
     */
    @Override
    public boolean batchTbAsset(List<TbAsset> tbAssetList) {
        int success = 0;
        List<SysDept> deptList = sysDeptMapper.allDept();
        List<TbAssetCategory> assetCategoryList = tbAssetCategoryMapper.selectList(null);
        for (TbAsset tbAsset : tbAssetList) {
            if (StrUtil.isNotBlank(tbAsset.getBarCode())) {
                long count = deptList.stream().filter(sysDept -> sysDept.getDeptId().equals(tbAsset.getDeptId())).count();
                List<SysDept> collect = deptList.stream().filter(sysDept -> sysDept.getDeptName().equals(tbAsset.getDeptName())).collect(Collectors.toList());
                SysDept dept = null;
                if (!collect.isEmpty()) {
                    dept = collect.get(0);
                }

                long count1 = assetCategoryList.stream().filter(tbAssetCategory -> tbAssetCategory.getNumber().equals(tbAsset.getCategoryNumber())).count();
                if ((count > 0 || dept != null) && count1 > 0) {
                    if (dept != null) {
                        tbAsset.setDeptId(dept.getDeptId());
                    }
                    int replace = tbAssetMapper.replace(tbAsset);
                    if (replace > 0) {
                        success++;
                    }
                }
            }
        }
        return success != 0;
    }

    /**
     * 数据导出
     *
     * @param asset 资产信息
     * @return 资产信息集合
     */
    @Override
    public List<TbAsset> exportData(TbAsset asset) {
        List<SysDept> deptList = sysDeptMapper.allDept();
        List<TbAsset> assetList = selectTbAssetList(asset);
        for (TbAsset tbAsset : assetList) {
            List<SysDept> collect = deptList.stream().filter(sysDept -> sysDept.getDeptId().equals(tbAsset.getDeptId())).collect(Collectors.toList());
            SysDept sysDept = collect.get(0);
            tbAsset.setDeptName(sysDept.getDeptName());
        }
        return assetList;
    }

    /**
     * 小程序：获取资产信息
     *
     * @param barCode 资产条形码
     * @param numberOrName 资产编号或名称
     * @return 资产信息（含借用信息）集合
     */
    @Override
    public List<TbAssetDTO> selectTbAsset(String barCode, String numberOrName) {
        if (StrUtil.isBlank(barCode) && StrUtil.isBlank(numberOrName)) {
            return Collections.emptyList();
        }
        List<TbAsset> assetList = new ArrayList<>();
        if (StrUtil.isNotBlank(barCode)) {
            TbAsset asset = query().eq("bar_code", barCode).one();
            assetList.add(asset);
        } else {
            assetList = query().like("bar_code", numberOrName).or().like("number", numberOrName).or().like("name", numberOrName).list();
        }

        assetList = assetList.stream().filter(Objects::nonNull).collect(Collectors.toList());

        if (assetList.isEmpty()) {
            return Collections.emptyList();
        }

        return find(assetList);
    }

    @Override
    public Page<TbAssetDTO> selectTbAssetPage(Integer pageNum, Integer pageSize, String numberOrName) {

        Page<TbAsset> tbAssetPage = new Page<>(pageNum, pageSize);

        QueryWrapper<TbAsset> queryWrapper = null;

        if (StrUtil.isNotBlank(numberOrName)) {
            queryWrapper = new QueryWrapper<>();
            queryWrapper.like("bar_code", numberOrName).or().like("number", numberOrName).or().like("name", numberOrName);
        }

        page(tbAssetPage, queryWrapper);

        List<TbAsset> assetList = tbAssetPage.getRecords();


        assetList = assetList.stream().filter(Objects::nonNull).collect(Collectors.toList());

        if (assetList.isEmpty()) {
            Page<TbAssetDTO> dtoPage = new Page<>();
            dtoPage.setRecords(Collections.emptyList());
            dtoPage.setTotal(tbAssetPage.getTotal());
            dtoPage.setCurrent(tbAssetPage.getCurrent());
            dtoPage.setPages(tbAssetPage.getPages());
            dtoPage.setSize(tbAssetPage.getSize());

            return dtoPage;
        }

        ArrayList<TbAssetDTO> assetDTOS = find(assetList);

        Page<TbAssetDTO> dtoPage = new Page<>();
        dtoPage.setRecords(assetDTOS);
        dtoPage.setTotal(tbAssetPage.getTotal());
        dtoPage.setCurrent(tbAssetPage.getCurrent());
        dtoPage.setPages(tbAssetPage.getPages());
        dtoPage.setSize(tbAssetPage.getSize());

        return dtoPage;
    }

    @Override
    public AjaxResult countTbAsset() {
        int allAsset = tbAssetMapper.countTbAssetAll();
        int faultAsset = tbAssetMapper.countTbAssetByStatus(TbAssetStatusEnum.fault.getStatusCode());
        int scrapAsset = tbAssetMapper.countTbAssetByStatus(TbAssetStatusEnum.scrap.getStatusCode());
        int borrowAsset = tbAssetBorrowRecordMapper.countTbAssetBorrowRecordForNotReturn();

        Map<String, Integer> resultMap = new HashMap<>();
        resultMap.put("allAsset", allAsset); // 全部设备
        resultMap.put("faultAsset", faultAsset); // 故障设备
        resultMap.put("scrapAsset", scrapAsset); // 报废设备
        resultMap.put("borrowAsset", borrowAsset); // 借出设备
        return AjaxResult.success("查询成功", resultMap);
    }

    private ArrayList<TbAssetDTO> find(List<TbAsset> assetList) {
        List<SysDept> deptList = sysDeptMapper.allDept();

        Long loginUserId = UserUtils.getLoginUserId();

        ArrayList<TbAssetDTO> assetDTOList = new ArrayList<>();
        for (TbAsset tbAsset : assetList) {
            List<SysDept> collect = Collections.emptyList();
            if (tbAsset.getDeptId() != null) {
                collect = deptList.stream().filter(sysDept -> sysDept.getDeptId().equals(tbAsset.getDeptId())).collect(Collectors.toList());
            }
            if (!collect.isEmpty()) {
                SysDept sysDept = collect.get(0);
                tbAsset.setDeptName(sysDept.getDeptName());
            }
            TbAssetDTO tbAssetDTO = BeanUtil.toBean(tbAsset, TbAssetDTO.class);
            if (tbAsset.getStatus() != 1) {
                tbAssetDTO.setBorrowStatus("不可借");
                assetDTOList.add(tbAssetDTO);
                continue;
            }
            QueryWrapper<TbAssetBorrowRecord> borrowRecordQueryWrapper = new QueryWrapper<>();
            borrowRecordQueryWrapper.eq("asset_bar_code", tbAsset.getBarCode()).eq("isReturn", 0);
            TbAssetBorrowRecord borrowRecord = tbAssetBorrowRecordMapper.selectOne(borrowRecordQueryWrapper);
            if (borrowRecord == null) {
                tbAssetDTO.setBorrowStatus("可借出");
                assetDTOList.add(tbAssetDTO);
                continue;
            }

            tbAssetDTO.setBorrowStatus("已借出");
            Long userId = borrowRecord.getUserId();
            SysUser sysUser = sysUserMapper.selectUserById(userId);
            tbAssetDTO.setBorrowUserName(sysUser.getUserName());
            tbAssetDTO.setBorrowDate(borrowRecord.getBorrowDate());
            tbAssetDTO.setReturnDate(borrowRecord.getReturnDate());
            tbAssetDTO.setTel(borrowRecord.getTel());
            tbAssetDTO.setMeBorrow(borrowRecord.getUserId().equals(loginUserId));

            assetDTOList.add(tbAssetDTO);
        }

        return assetDTOList;
    }
}
