package com.yeejoin.equipmanage.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.equipmanage.common.entity.*;
import com.yeejoin.equipmanage.common.entity.vo.*;
import com.yeejoin.equipmanage.common.vo.EquipmentVo;
import com.yeejoin.equipmanage.fegin.PatrolFeign;
import com.yeejoin.equipmanage.mapper.*;
import com.yeejoin.equipmanage.remote.RemoteSecurityService;
import com.yeejoin.equipmanage.service.IEquipmentDetailService;
import com.yeejoin.equipmanage.service.IEquipmentIndexService;
import com.yeejoin.equipmanage.service.IEquipmentService;
import com.yeejoin.equipmanage.service.IUnitService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

/**
 * 服务实现类
 *
 * @author wujiang
 * @date 2020-07-07
 */
@Service
public class EquipmentServiceImpl extends ServiceImpl<EquipmentMapper, Equipment> implements IEquipmentService {

    @Autowired
    private EquipmentMapper equipmentMapper;
    @Autowired
    private EquipmentDetailMapper equipmentDetailMapper;
    @Autowired
    private CarMapper carMapper;
    @Autowired
    private EquipmentIndexMapper equipmentIndexMapper;
    @Autowired
    private EquipmentCategoryMapper equipmentCategoryMapper;
    @Autowired
    private IEquipmentIndexService iEquipmentIndexService;
    @Autowired
    private IUnitService iUnitService;
    @Lazy
    @Autowired
    private UploadFileMapper uploadFileMapper;
    @Autowired
    private ManufacturerInfoMapper manufacturerInfoMapper;
    @Autowired
    private PatrolFeign patrolFeign;
    @Autowired
    private RemoteSecurityService remoteSecurityService;
    @Lazy
    @Autowired
    private IEquipmentDetailService iEquipmentDetailService;

    @Autowired
    private RedisUtils redisUtils;

    // 装备分类code长度
    private static final int CATECODELEN = 8;
    private String proviceCode = "44";

    @Override
    public List<Map<String, Object>> getWlZbdyByCondition(String daoCriteria, String isIot, Long maxResult, Long firstResult) {
        List<Map<String, Object>> result = equipmentMapper.getEquipmentList(daoCriteria, isIot, firstResult, maxResult);
        return result;
    }

    @Override
    public Long getWlZbdyRowNum(String daoCriteria) {
        long count = equipmentMapper.getEquipmentCount(daoCriteria);
        return count;
    }

    @Override
    public void deleteEquipments(List<Long> idList) throws IllegalArgumentException {
        List<Equipment> equipments = new ArrayList<>();// 将要被删除的equipment
        idList.stream().forEach(id -> {

            Equipment equipment = equipmentMapper.selectById(id);
            if (equipment == null) {
                equipments.clear();// 有一个查不到则全部discard
                throw new IllegalArgumentException("无此装备记录");
            }
            Map<String, Object> columnMap = new HashMap<String, Object>();
            columnMap.put("equipment_id", id);

            List<EquipmentDetail> equipmentDetails = equipmentDetailMapper.selectByMap(columnMap);
            List<Car> cars = carMapper.selectByMap(columnMap);
            if ((equipmentDetails != null && equipmentDetails.size() > 0) || !cars.isEmpty()) {
                equipments.clear();
                throw new IllegalArgumentException("此装备已被使用");
            }
            equipments.add(equipment);

        });

        try {
            // 现在可以删除操作
            equipments.stream().forEach(equipment -> {
                Map<String, Object> columnMap = new HashMap<String, Object>();
                columnMap.put("equipment_id", equipment.getId());
                List<EquipmentIndex> perfQuotas = equipmentIndexMapper.selectByMap(columnMap);
                if (!perfQuotas.isEmpty()) {
                    List<Long> ids = new ArrayList<>();
                    for (EquipmentIndex p : perfQuotas) {
                        ids.add(p.getId());
                    }
                    equipmentIndexMapper.deleteBatchIds(ids);
                }
                equipmentMapper.deleteById(equipment.getId());
            });
            refreshData();
        } catch (Exception e) {
            throw new RuntimeException("删除失败！");
        }
    }

    @Override
    public boolean addEquipmentDef(Equipment equipment) throws IllegalArgumentException {
            // 查询装备定义名陈是否重复
            nameDuplicate(equipment);
            // 设置code属性
            EquipmentCategory category = equipmentCategoryMapper.selectById(equipment.getCategoryId());
            String code = null; // 装备定义编码
            if (category != null) {
                code = generateEquipCode(category.getId(), category.getCode());
                equipment.setCode(code);
            }
            int num = equipmentMapper.insert(equipment);

//            saveEquipmentQRCodes(equipment);
            JSONObject equipRuleParams = new JSONObject();
            equipRuleParams.put("name", equipment.getName());
            equipRuleParams.put("inspectionSpecId", equipment.getInspectionSpec());
            try {
                patrolFeign.getEquipDetail(equipRuleParams.toJSONString());
            } catch (Exception e) {
                log.error("新增装备定义操作中，检测到巡检服务未启动或启动出错！");
            }
            if (num > 0) {
                refreshData();
                return true;
            }
            return false;
        }

        @Async
        public void refreshData() {
            if (redisUtils.hasKey("equip_equipDefinitions")) {
                redisUtils.del("equip_equipDefinitions");
            }
            QueryWrapper<Equipment> equipmentQueryWrapper = new QueryWrapper<>();
            equipmentQueryWrapper.isNotNull("id");
            List<Equipment> equipments = equipmentMapper.selectList(equipmentQueryWrapper);
            redisUtils.set("equip_equipDefinitions", JSONObject.toJSONString(equipments));
        }

//    public void saveEquipmentQRCodes(Equipment equipment) {
//        try {
//            EquipmentdefQrcode code = EquipmentdefQrcode.getBuilder().withEquipmentId(() -> equipment.getId()).build();
//            int savedCode = equipmentdefQrcodeMapper.insert(code);
//            code.getCreateDate().getTime();
//
//            String qrcode = QRCodeUtil.generateQRCode();
//
//            code.setQRCode(qrcode);
//            equipmentdefQrcodeMapper.updateById(code);
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new RuntimeException("装备二维码保存失败！");
//        }
//    }

    /**
     * 生成装备定义code
     *
     * @author as-wanglei
     */
    public String generateEquipCode(Long categoryId, String code) {
        StringBuffer sbuffer = new StringBuffer();
        sbuffer.append(code);
        sbuffer.append(generateSuffix(categoryId));
        sbuffer.append(proviceCode);
        return sbuffer.toString();
    }

    private StringBuffer generateSuffix(Long categoryId) {
        StringBuffer sbuffer = new StringBuffer();

        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("category_id", categoryId);
        List<Equipment> equipments = equipmentMapper.selectByMap(columnMap);
        // 截取后5位
        List<String> codes = equipments.stream().map(e -> e.getCode().substring(CATECODELEN, e.getCode().length() - 2))
                .collect(Collectors.toList());
        // 截取后5位
        String suffix = null;
        while (true) {
            boolean same = false;
            suffix = RandomStringUtils.random(3, true, true);
            for (String code : codes) {
                if (code.equals(suffix)) {
                    same = true;
                }
            }
            if (!same) {
                break;
            }
        }
        sbuffer.append(suffix.toUpperCase());
        return sbuffer;

    }

    @Override
    public boolean editEquipmentDef(Equipment equipment1) throws IllegalArgumentException {
        // 首先检测是否被使用 --- 若使用则不能修改
        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("equipment_id", equipment1.getId());
        List<EquipmentDetail> equipmentDetails = equipmentDetailMapper.selectByMap(columnMap);
        List<Car> cars = carMapper.selectByMap(columnMap);
        Equipment nowEquipment = this.baseMapper.selectById(equipment1.getId());
        if (!(equipment1.getCategoryId()).equals(nowEquipment.getCategoryId()) && (!equipmentDetails.isEmpty() || !cars.isEmpty())) {
            throw new IllegalArgumentException("此装备已被使用，不能修改分类类型");
        } else {
            nameDuplicate(equipment1, true);// 名称是否重复
            // equipment = settingCodeProperty(equipment);//设置code属性
            equipment1.setDateUpdated(new Date());
            if (equipment1.getImg() == null) {
                equipment1.setImg("");
            }
            int savedEquipment = equipmentMapper.updateById(equipment1);
            iEquipmentDetailService.update(new UpdateWrapper<EquipmentDetail>().eq("equipment_id", equipment1.getId())
                    .set("name", equipment1.getName())
                    .set("expiry_date", equipment1.getExpiryDate())
            .set("maintenance_cycle", equipment1.getMaintenanceCycle()));
            JSONObject equipRuleParams = new JSONObject();
            equipRuleParams.put("name", equipment1.getName());
            equipRuleParams.put("inspectionSpecId", equipment1.getInspectionSpec());
            try {
                patrolFeign.getEquipDetail(equipRuleParams.toJSONString());
            } catch (Exception e) {
                log.error("编辑装备定义操作中，检测到巡检服务未启动或启动出错！");
            }
            if (savedEquipment > 0) {
                refreshData();
                return true;
            }
            return false;
        }

    }

    /**
     * 判断名称是否录入重复
     *
     * @param equipment
     */
    private void nameDuplicate(Equipment equipment) throws IllegalArgumentException {
        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("name", equipment.getName());
        List<Equipment> existEquipments = equipmentMapper.selectByMap(columnMap);
        if (existEquipments != null && existEquipments.size() > 0) {
            throw new IllegalArgumentException("录入的装备名称重复");
        }
    }

    /**
     * 判断名称是否录入重复,若flag为true，则必须保证equipment有id属性 否则跑出illegalArgumentException
     *
     * @param equipment
     */
    private void nameDuplicate(Equipment equipment, boolean flag) throws IllegalArgumentException {
        if (flag) {
            if (equipment.getId() == null) {
                throw new IllegalArgumentException("编辑时id不能为NULL");
            }
            Map<String, Object> columnMap = new HashMap<String, Object>();
            columnMap.put("name", equipment.getName());
            List<Equipment> existEquipments = equipmentMapper.selectByMap(columnMap);
            if (existEquipments != null && existEquipments.size() > 0
                    && !(existEquipments.get(existEquipments.size() - 1).getId()).equals(equipment.getId())) {
                throw new IllegalArgumentException("录入的装备名称重复");
            }
        } else {
            nameDuplicate(equipment);
        }

    }

    @Override
    public List<Map<String, Object>> queryPerfQuotaByCondition(Long equipId, Long maxResult, Long firstResult) {
        return equipmentIndexMapper.queryEquipmentIndexListByEquipId(equipId, firstResult, maxResult);

    }

    @Override
    public long countPerfQuotaByCondition(Long equipId) {
        return equipmentIndexMapper.queryEquipmentIndexCountByEquipId(equipId);

    }

    @Override
    public List<Equipment> findAllByCategoryId(Long categoryId) {
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<Equipment>();
        queryWrapper.lambda().eq(Equipment::getCategoryId, categoryId);
        return this.list(queryWrapper);
    }

    @Override
    public List<Equipment> listByCategoryId(Long categoryId) {
        List<Equipment> list = this.list(new QueryWrapper<Equipment>().eq("category_id", categoryId));
        for (Equipment equipment : list) {
            List<EquipmentIndex> quotaList = iEquipmentIndexService
                    .list(new QueryWrapper<EquipmentIndex>().eq("equipment_id", equipment.getId()));
            List<EquProperty> properList = new ArrayList<EquProperty>();
            for (EquipmentIndex equipmentIndex : quotaList) {
                EquProperty equProperty = new EquProperty();
                equProperty.setEquipmentIndexId(equipmentIndex.getId());
                equProperty.setPerfQuotaName(equipmentIndex.getPerfQuotaName());
                equProperty.setEquipmentIndexName(equipmentIndex.getPerfQuotaName());
                equProperty.setGroupName(equipmentIndex.getGroupName());
                equProperty.setValue(equipmentIndex.getPerfValue());
                equProperty.setUnitName(equipmentIndex.getUnitName());
                equProperty.setEquipmentIndexKey(equipmentIndex.getPerfQuotaDefinitionId());
                properList.add(equProperty);
            }
            equipment.setEquPropertyList(properList);
            Unit unit = iUnitService.getById(equipment.getUnitId());
            equipment.setUnit(unit);

        }
        return list;
    }

    @Override
    public List<Equipment> categoryList() {
        List<Equipment> list = this.list();
        Map<String, List<EquipmentIndex>> equipmentIndexMap = iEquipmentIndexService.list().stream()
                .collect(Collectors.groupingBy(EquipmentIndex::getEquipmentId));
        Map<Long, Unit> unitMap = iUnitService.list().stream().collect(Collectors.toMap(Unit::getId, t -> t));
        Map<Long, EquipmentCategory> categoryMap = equipmentCategoryMapper.selectList(null).stream().collect(Collectors.toMap(EquipmentCategory::getId, t -> t));
        for (int i = 0; i <list.size(); i++) {
            Equipment equipment = list.get(i);
            EquipmentCategory equipmentCategory = categoryMap.get(equipment.getCategoryId());
            String categoryCode = equipment.getCode();
            // 移除非消耗性设备
            if (Objects.isNull(equipmentCategory) || !Objects.equals(equipmentCategory.getIndustryCode(), "2") || categoryCode.charAt(0) == '2' || categoryCode.charAt(0) == '9') {
                list.remove(equipment);
                i--;
                continue;
            }
            List<EquipmentIndex> quotaList = equipmentIndexMap.get(equipment.getId().toString());
            List<EquProperty> properList = new ArrayList<EquProperty>();
            if (CollUtil.isNotEmpty(quotaList)) {
                for (EquipmentIndex equipmentIndex : quotaList) {
                    EquProperty equProperty = new EquProperty();
                    equProperty.setEquipmentIndexId(equipmentIndex.getId());
                    equProperty.setPerfQuotaName(equipmentIndex.getPerfQuotaName());
                    equProperty.setEquipmentIndexName(equipmentIndex.getPerfQuotaName());
                    equProperty.setGroupName(equipmentIndex.getGroupName());
                    equProperty.setValue(equipmentIndex.getPerfValue());
                    equProperty.setUnitName(equipmentIndex.getUnitName());
                    equProperty.setEquipmentIndexKey(equipmentIndex.getPerfQuotaDefinitionId());
                    properList.add(equProperty);
                }
            }
            if (ObjectUtils.isNotEmpty(equipmentCategory)) {
                equipment.setEquipCategoryId(equipmentCategory.getId());
                equipment.setEquipCategoryCode(equipmentCategory.getCode());
                equipment.setEquipCategoryName(equipmentCategory.getName());
            }
            equipment.setEquPropertyList(properList);
            equipment.setUnit(unitMap.get(equipment.getUnitId()));
        }
        return list;
    }

    @Override
    public EquipmentAppVO getEquipmentAppMessage(String qrCode) {
        EquipmentAppVO equipmentApp = new EquipmentAppVO();
        //设备信息参数
        EquipmentBaseAppVO equipmentBaseApp = equipmentMapper.getEquipmentAppMessage(qrCode);
        if (equipmentBaseApp == null) {
            equipmentBaseApp = new EquipmentBaseAppVO();
        }
        QueryWrapper<UploadFile> imgQueryWrapper = new QueryWrapper<>();
        imgQueryWrapper.eq("object_id", equipmentBaseApp.getEquipDetailId());
        imgQueryWrapper.eq("file_type", "image");
        List<UploadFile> uploadFiles = uploadFileMapper.selectList(imgQueryWrapper);
        for (UploadFile s : uploadFiles) {
            s.setUrl(s.getUrl());
        }
        equipmentBaseApp.setImg(uploadFiles);
        equipmentApp.setEquipmentBase(equipmentBaseApp);
        //技术文档
        QueryWrapper<UploadFile> excelQueryWrapper = new QueryWrapper<>();
        excelQueryWrapper.eq("object_id", equipmentBaseApp.getEquipDetailId());
        excelQueryWrapper.eq("file_type", "instruction");
        List<UploadFile> uploadFiles1 = uploadFileMapper.selectList(excelQueryWrapper);
        for (UploadFile s : uploadFiles1) {
            s.setUrl(s.getUrl());
        }
        equipmentApp.setExcel(uploadFiles1);
        //性能指标,带指标值
        List<EquipmentIndexVO> voList = this.baseMapper.querySpecificIndexList(equipmentBaseApp.getEquipmentSpecificId());
        equipmentApp.setEquipmentIndexVOS(voList);
        //供应商
        QueryWrapper<ManufacturerInfo> manufacturerInfoQueryWrapper = new QueryWrapper<>();
        manufacturerInfoQueryWrapper.eq("id", equipmentBaseApp.getManufacturerId());
        equipmentApp.setManufacturerInfo(manufacturerInfoMapper.selectOne(manufacturerInfoQueryWrapper));
        return equipmentApp;
    }

    @Override
    public String checkDelete(List<Long> ids) {
        List<String> s = manufacturerInfoMapper.checkDelete(ids);
        return String.join(",", s);
    }

    @Override
    public List<ImportantEquipmentVO> getImportantEquipmentList(List<Long> ids) {
        List<ImportantEquipmentVO> list = this.baseMapper.getImportantEquipmentList(ids);
        StringBuilder userIds = new StringBuilder();
        StringBuilder deptIds = new StringBuilder();
        int i = 0;
        list.forEach(x -> {
            if (i == 0) {
                if (x.getChargeUserId() != null) {
                    userIds.append(x.getChargeUserId());
                    if (x.getChargeDeptId() != null) {
                        deptIds.append(x.getChargeDeptId());
                    }
                } else {
                    if (x.getChargeUserId() != null) {
                        userIds.append(',' + x.getChargeUserId());
                        if (x.getChargeDeptId() != null) {
                            deptIds.append(',' + x.getChargeDeptId());
                        }
                    }
                }
            }
        });
        Map<String, String> usermap = new HashMap<>();
        Map<String, String> deptmap = new HashMap<>();
        if (userIds.length() > 0) {
            List<AgencyUserModel> agencyUserModels = remoteSecurityService.listUserByUserIds(userIds.toString());
            if (deptIds.length() > 0) {
                List<HashMap<String, String>> agencyDeptModels = remoteSecurityService.listDeptByDeptIds(deptIds.toString());
                agencyDeptModels.forEach(z -> {
                    deptmap.put(z.get("sequenceNbr"), z.get("departmentName"));
                });
            }
            agencyUserModels.forEach(y -> {
                usermap.put(y.getUserId(), y.getRealName());
            });
        }

        list.forEach(x -> {
            if (usermap.size() > 0) {
                x.setChargeUserName(usermap.get(x.getChargeUserId().toString()));
            }
            if (deptmap.size() > 0) {
                x.setChargeDeptName(deptmap.get(x.getChargeDeptId().toString()));
            }
            List<PreplanPictureVO> images = x.getImages();
            if (images != null && images.size() > 0) {
                images.forEach(a -> {
                    String picture = a.getPicture();
                    if (StringUtils.isNotEmpty(picture)) {
                        a.setPicture(picture);
                    }
                });
            }

        });
        return list;
    }

    @Override
    public List<EquipmentVo> getEquipListBySpecific() {
        List<EquipmentVo> list = equipmentMapper.getEquipListBySpecific();
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }
        return Lists.newArrayList();
    }
	@Override
	public List<Map<String, Object>> getEquipmentNameAndCode() {
		  QueryWrapper<Equipment> queryWrapper = new QueryWrapper<Equipment>();
		  queryWrapper.select("code","name");
		return equipmentMapper.selectMaps(queryWrapper);
	}

    @Override
    public List<Equipment> getAll() {
        return this.list();
    }

    @Override
    public List<Equipment> getAllByCode(String id) {
        if (StringUtils.isNotEmpty(id)) {
            EquipmentCategory category = equipmentCategoryMapper.selectOne(new LambdaQueryWrapper<EquipmentCategory>().eq(EquipmentCategory::getId, Long.valueOf(id)));
            QueryWrapper<Equipment> queryWrapper = new QueryWrapper<Equipment>();
            queryWrapper.likeRight("code", category.getCode().substring(0,4));
            queryWrapper.ne("id", Long.valueOf(id));
            return equipmentMapper.selectList(queryWrapper);
        } else {
            return this.list();
        }
    }

	@Override
	public EquipmentVo getEquipBySpecific(Long equipmentSpecificId)
	{
		return equipmentMapper.getEquipBySpecific(equipmentSpecificId);
	}
}
