package com.yeejoin.amos.fas.business.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yeejoin.amos.fas.business.constants.FasConstant;
import com.yeejoin.amos.fas.business.dao.mapper.*;
import com.yeejoin.amos.fas.business.dao.repository.IEquipmentDao;
import com.yeejoin.amos.fas.business.dao.repository.IEquipmentFireEquipmentDao;
import com.yeejoin.amos.fas.business.dao.repository.IPreplanPictureDao;
import com.yeejoin.amos.fas.business.feign.IEquipManageFeign;
import com.yeejoin.amos.fas.business.feign.RemoteSecurityService;
import com.yeejoin.amos.fas.business.param.ImgParam;
import com.yeejoin.amos.fas.business.service.intfc.EquipmentSpecificService;
import com.yeejoin.amos.fas.business.service.intfc.IEquipmentService;
import com.yeejoin.amos.fas.business.vo.EquipCommunicationData;
import com.yeejoin.amos.fas.core.common.request.CommonPageable;
import com.yeejoin.amos.fas.core.common.response.EquipDetailsResponse;
import com.yeejoin.amos.fas.core.util.DaoCriteria;
import com.yeejoin.amos.fas.core.util.query.BaseQuerySpecification;
import com.yeejoin.amos.fas.dao.dto.EquipmentDTO;
import com.yeejoin.amos.fas.dao.entity.*;
import com.yeejoin.amos.fas.exception.YeeException;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.privilege.model.DepartmentModel;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

@Service("equipService")
public class EquipmentServiceImpl implements IEquipmentService {

    private final Logger log = LoggerFactory.getLogger(EquipmentServiceImpl.class);

    private final String[] docxTitle = {"设备编号", "设备名称", "所属区域", "位置"};

    @Autowired
    ImpEquipMapper impEquipMapper;

    @Autowired
    FireEquipMapper fireEquipMapper;

    @Autowired
    EquipmentSpecificMapper equipmentSpecificMapper;

    @Autowired
    IEquipmentDao iEquipmentDao;
    @Autowired
    IPreplanPictureDao iPreplanPictureDao;

    @Autowired
    IEquipmentFireEquipmentDao equipmentFireEquipmentDao;

    @Autowired
    ImpAndFireEquipMapper impAndFireEquipMapper;

    @Autowired
    private IPreplanPictureDao preplanPictureDao;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PlanEquipmentMapper planEquipmentMapper;

    @Autowired
    IEquipManageFeign iEquipManageFeign;

    @Value("${windows.img.path}")
    private String winImgPath;

    @Value("${linux.img.path}")
    private String linuxImgPath;

    @Value("${server.servlet.context-path}")
    private String fireAutoSys;

	@Autowired
	private RemoteSecurityService remoteSecurityService;

    public Equipment save(Equipment equipment) {
        Long eqId = equipment.getId();
        equipment = iEquipmentDao.saveAndFlush(equipment);
        return equipment;
    }


    public Equipment queryOne(Long id) {

    	Optional<Equipment> dict1=iEquipmentDao.findById(id);
    	Equipment  dict=null;
		if(dict1.isPresent()){
			dict=dict1.get();
		}
		return dict;

    }

    @Override
    @Transactional
    public String[] delete(String[] idArray) throws Exception {
        List<Long> idList = new ArrayList<>();
        for (String id : idArray) {
            Optional<Equipment> equipment1 = iEquipmentDao.findById(Long.parseLong(id));
        	Equipment  equipment=null;
    		if(equipment1.isPresent()){
    			equipment=equipment1.get();
    		}
            if (equipment != null) {
            	List<EquipmentFireEquipment> eqFireEqs = equipmentFireEquipmentDao.findAllByEquipmentId(equipment.getId());

            	if(!eqFireEqs.isEmpty()){
            		equipmentFireEquipmentDao.deleteAll(eqFireEqs);
            	}
                this.iEquipmentDao.deleteById(Long.parseLong(id));
            } else {
                throw new Exception("找不到指定的对象:" + id);
            }
            idList.add(Long.valueOf(id));
            //删除重点设备关联关系
            equipmentFireEquipmentDao.deleteByEquipmentId(Long.valueOf(id));
        }
        // 同步至数字预案
        planEquipmentMapper.logicDeleteByEquipIdList(idList);

        return idArray;
    }


    @Override
    public List<PreplanPicture> queryImgByIdAndType(List<DaoCriteria> criterias) {
        BaseQuerySpecification<PreplanPicture> spec = new BaseQuerySpecification<>(criterias);
        return iPreplanPictureDao.findAll(spec);
    }

    @Override
    public Page<Equipment> queryImpEquip(List<DaoCriteria> criterias, CommonPageable commonPageable) {
        String name = "";
        String id = "";
        for (DaoCriteria criteria : criterias) {
            if (criteria.getPropertyName().equals("name")) {
                name = String.valueOf(criteria.getValue() != null ? criteria.getValue().toString() : "");
            }
            if (criteria.getPropertyName().equals("id")) {
                id = String.valueOf(criteria.getValue() != null ? criteria.getValue().toString() : "");
            }
        }
        Long total = impEquipMapper.getEquipPageCount(name, id);
        List<Map> content = impEquipMapper.getEquipPage(name, id, commonPageable.getOffset(),
                commonPageable.getPageSize());
        Page result = new PageImpl(content, commonPageable, total);
        return result;
    }

    @Override
    public List<Equipment> queryEquipNoPage() {
        return iEquipmentDao.findAll();
    }


    /**
     * 绑定消防设备
     *
     * @param list
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public List<Map<String, Object>> bindFireEqumt(Long equipmentId, List<EquipmentFireEquipment> list) throws Exception {
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (EquipmentFireEquipment equipmentFireEquipment : list) {
            EquipmentSpecific equip  = equipmentSpecificMapper.getSpecificById(equipmentFireEquipment.getFireEquipmentId());
            int num = equipmentSpecificMapper.getOneByQrcode(equip.getQrCode());
            if (0 < num) {
                throw new RuntimeException("已报废装备不能添加为配套设备！");
            }
            int count = equipmentFireEquipmentDao.findByEqmtIdAndFireEqmtId(equipmentId, equipmentFireEquipment.getFireEquipmentId());
            if (count > 0) {
                continue;
            }
            equipmentFireEquipment.setEquipmentId(equipmentId);
            equipmentFireEquipment.setCreateDate(new Date());
            Map<String, Object> result = new HashMap<>();
            result.put("exits", false);
            Equipment equipment = this.iEquipmentDao.getOne(equipmentFireEquipment.getEquipmentId().longValue());

            String equipmentSpecific =  equipmentSpecificMapper.findEquipNameById(equipmentFireEquipment.getFireEquipmentId());
            if (equipment == null || StringUtils.isEmpty(equipmentSpecific))
                throw new RuntimeException("找不到数据");
            this.equipmentFireEquipmentDao.save(equipmentFireEquipment);
            //已存在的绑定关系
            List<EquipmentFireEquipment> exits = impAndFireEquipMapper.queryForList(String.valueOf(equipmentFireEquipment.getFireEquipmentId()), null);
            if (!CollectionUtils.isEmpty(exits))
                result.put("exits", true);
            result.put("newModel", equipmentFireEquipment);
            resultList.add(result);
        }
        return resultList;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> removeFireEqmtBind(Long equipmentId, String[] fireEquipmentIds) {
        List<Long> ids = new ArrayList<>();
        for (String id : fireEquipmentIds) {
            long result = 0;
            EquipmentFireEquipment equipmentFireEquipment = impAndFireEquipMapper.queryForOne(String.valueOf(id), String.valueOf(equipmentId));

            if (equipmentFireEquipment != null) {
                result = equipmentFireEquipment.getId();
                this.equipmentFireEquipmentDao.deleteById(equipmentFireEquipment.getId());
                fireEquipMapper.removeIfmeaPointByFireEquipIdAndEquipId(Long.valueOf(id), equipmentId);
                //iFmeaEquipmentPointDao.removeByFireEquipIdAndEquipId(Long.valueOf(id), equipmentId);
            }
            ids.add(result);
        }

        return ids;
    }


    /**
     * 查询指定重点设备已经绑定的消防设备
     *
     * @param equipmentId
     * @return
     */
    @Override
    public Page queryBindFirEqumtList(CommonPageable commonPageable, Long equipmentId) {
//    	long start = -1;
//        int length = -1;
//        if (null != commonPageable) {
//            start = commonPageable.getOffset();
//            length = commonPageable.getPageSize();
//        }
//        long total = this.impAndFireEquipMapper.queryBindFirEqumtPageCount(String.valueOf(equipmentId));
//        List<FireEquipment> list = this.impAndFireEquipMapper.queryBindFirEqumtPage(start, length, String.valueOf(equipmentId));
//        if(commonPageable==null)
//        {
//        	commonPageable = new CommonPageable();
//        }
//        Page result = new PageImpl(list, commonPageable, total);
        return null;
    }

    @Override
    public Page reservePage(CommonPageable commonPageable) {
        long start = -1;
        int length = -1;
        if (null != commonPageable) {
            start = commonPageable.getOffset();
            length = commonPageable.getPageSize();
        }
        long total = this.impEquipMapper.reservePageCount();
        List<EquipmentDTO> list = this.impEquipMapper.reservePage(start, length);
        if(commonPageable==null)
        {
            commonPageable = new CommonPageable();
        }
        Page result = new PageImpl(list, commonPageable, total);
        return result;
    }

    @Override
    public Equipment saveImg(MultipartFile file, Equipment equipment, int type, Long userId) {
        // TODO Auto-generated method stub
        Long equipmentId = Long.valueOf(equipment.getId());

        PreplanPicture pp = preplanPictureDao.selectOne(equipmentId, type);
        if (pp == null) {
            pp = new PreplanPicture();
            pp.setEquipmentId(equipmentId);
            pp.setType(type);
            pp.setCreateDate(new Date());
            pp.setCreateBy(userId.intValue()+"");
        }

        String path = FasConstant.UPLOAD_ROOT_PATH + File.separator + FasConstant.UPLOAD_EQUIPMENT_PATH + File.separator
                + equipment.getId();
        String filePath = getRootPath() + path;

        String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."),
                file.getOriginalFilename().length());
        String fileName = File.separator + type + fileType;

        try {
            File dest = new File(filePath + File.separator + fileName);
            if (!dest.exists()) {
                if (dest.getParentFile() != null && !dest.getParentFile().exists()) {
                    dest.getParentFile().mkdirs();
                }
                dest.createNewFile();
            }
            file.transferTo(dest);
        } catch (IOException e) {
            throw new YeeException("上传图片失败");
        }
        String picture = path + fileName;
        pp.setCreateBy(userId.intValue()+"");
        pp.setPicture(picture);
        if (equipment.getCreateDate() == null) {
        	Optional<Equipment>  date=iEquipmentDao.findById(equipment.getId());
        	Equipment  equipment2=null;
    		if(date.isPresent()){
    			equipment2=date.get();
    		}
           equipment.setCreateDate(equipment2.getCreateDate());
        }

        preplanPictureDao.saveAndFlush(pp);
        equipment = iEquipmentDao.saveAndFlush(equipment);
        return equipment;
    }

    private String getRootPath() {
        String localPath = "";
        if ("\\".equals(File.separator)) {
            localPath += winImgPath;
        } else if ("/".equals(File.separator)) {
            localPath += linuxImgPath;
        }
        return localPath.trim();
    }


    @Override
    public Equipment saveEquipmentAndImg(ImgParam[] imgs, Equipment equipment) {
        String path = FasConstant.UPLOAD_ROOT_PATH + File.separator + FasConstant.UPLOAD_EQUIPMENT_PATH
                + File.separator + equipment.getId();
        String filePath = getRootPath() + path;
        preplanPictureDao.deletebyEqId(equipment.getId());
        File file1 = new File(filePath);
        if (file1.exists()){
            File[] files = file1.listFiles();
            if (files.length >0){
                for (File f:  files) {
                    f.delete();
                }
            }
        }
        // TODO Auto-generated method stub
        if (imgs == null || imgs.length < 1) {
            equipment = save(equipment);
            if (equipment.getCreateDate() == null) {

            	Optional<Equipment>  date=iEquipmentDao.findById(equipment.getId());
            	Equipment  equipment2=null;
        		if(date.isPresent()){
        			equipment2=date.get();
        		}

                equipment.setCreateDate(equipment2.getCreateDate() == null ? new Date() : equipment2.getCreateDate());
            }
        } else {
            equipment = save(equipment);
            if (equipment.getCreateDate() == null) {

            	Optional<Equipment>  date=iEquipmentDao.findById(equipment.getId());
            	Equipment  equipment2=null;
        		if(date.isPresent()){
        			equipment2=date.get();
        		}

                equipment.setCreateDate(equipment2.getCreateDate() == null ? new Date() : equipment2.getCreateDate());
            }
            Long equipmentId = Long.valueOf(equipment.getId());
            for (int i = 0; i < imgs.length; i++) {
                MultipartFile file = imgs[i].getFile();
                if (null != file) {
                    int type = imgs[i].getType();
                    PreplanPicture pp = preplanPictureDao.selectOne(equipmentId, type);
                    if (pp == null) {
                        pp = new PreplanPicture();
                        pp.setEquipmentId(equipmentId);
                        pp.setType(type);
                        pp.setCreateDate(new Date());
                    }


                    String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."),
                            file.getOriginalFilename().length());
                    Long startTs = System.currentTimeMillis();
                    String fileName = File.separator + type + "_"+startTs+ fileType;

                    try {
                        File dest = new File(filePath + File.separator + fileName);
                        if (!dest.exists()) {
                            if (dest.getParentFile() != null && !dest.getParentFile().exists()) {
                                dest.getParentFile().mkdirs();
                            }
                            dest.createNewFile();
                        }
                        file.transferTo(dest);
                    } catch (IOException e) {
                        log.error(e.getMessage(), e);
                        throw new YeeException("上传图片失败");
                    }
                    String[] split = fireAutoSys.split("/");
                    String picture = split[1]+"/"+path + fileName;
                    pp.setPicture(picture);
                    preplanPictureDao.saveAndFlush(pp);
                }
            }
            equipment = iEquipmentDao.saveAndFlush(equipment);
        }
        return equipment;
    }

    @Override
    public List<Map<String, Object>> findEquipVideoList() {
        List<Map<String, Object>> list = impAndFireEquipMapper.findEquipVideo();
        Map<String, Map<String, Object>> tempEquip = new HashMap<String, Map<String, Object>>();
        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
        for (Map<String, Object> temp : list) {
            Map<String, Object> equip = new HashMap<String, Object>();
            Map<String, Object> video = new HashMap<String, Object>();
            video.put("id", temp.get("id"));
            video.put("code", temp.get("code"));
            video.put("name", temp.get("name"));
            video.put("videoUrl", temp.get("url"));
            video.put("equipName", temp.get("equipName"));
            video.put("monitorTime", new Date());
            List<Map<String, Object>> videoList = new ArrayList<Map<String, Object>>();
            if (tempEquip.containsKey(temp.get("equipId").toString())) {
                equip = tempEquip.get(temp.get("equipId").toString());
                videoList = (List<Map<String, Object>>) equip.get("children");
                videoList.add(video);
            } else {
                equip.put("equipId", temp.get("equipId"));
                equip.put("equipName", temp.get("equipName"));
                equip.put("equipCode", temp.get("equipCode"));
                videoList.add(video);
                equip.put("children", videoList);
                tempEquip.put(temp.get("equipId").toString(), equip);
                result.add(equip);
            }
        }
        return result;
    }

    @Override
    public EquipDetailsResponse findEquipDetailsById(String toke,String product,String appKey,Long id) {
    	EquipDetailsResponse equipDetailsResponse =  fireEquipMapper.findEquipDetailsById(id);
    	AgencyUserModel user = remoteSecurityService.getUserById(toke, product, appKey, equipDetailsResponse.getUserId());
    	equipDetailsResponse.setUsername(user.getRealName());
    	equipDetailsResponse.setTel(user.getMobile());
    	if(user.getCompanys().get(0)!=null)
    	{
    		CompanyModel companyModel = user.getCompanys().get(0);
    		if(user.getCompanyDepartments().get(companyModel.getSequenceNbr())!=null)
    		{
    			List<DepartmentModel> departList = user.getCompanyDepartments().get(companyModel.getSequenceNbr());
    			if(!departList.isEmpty())
    			{
    				equipDetailsResponse.setDepName(departList.get(0).getDepartmentName());
    			}
    		}
    	}
        return equipDetailsResponse;
    }


    @Override
    public List<Equipment> findAll() {
        return iEquipmentDao.findAll();
    }

    @Override
    public EquipCommunicationData findFireEquipmentByPointCode(String code) {
    	EquipCommunicationData data = fireEquipMapper.findOneByPointCode(code);
        return data;
    }

    @Override
    public EquipCommunicationData findFireEquipDataByPointCode(String code) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("pointCode").is(code)).limit(1);
//        query.with(new Sort(new Order(Direction.DESC, "recDate")));
//        query.limit(1);
//        List<EquipCommunicationData> data = mongoTemplate.find(query, EquipCommunicationData.class);
//        if (data.isEmpty()) {
//            return null;
//        }
        return null;
    }


	@Override
	public int countImpEquipByIds(String[] idArray) {
		return equipmentFireEquipmentDao.countImpEquipByIds(idArray);
	}


	@Override
	public int countFemaRelation(String[] idArray) {
		return iEquipmentDao.countFemaRelation(idArray);
	}

    @Override
    public int countByStatus(int status) {
        return iEquipmentDao.countByStatus(status);
    }

    @Override
    public List<Object> getReserveEquipById(Long id, String typeCode) {

        return iEquipmentDao.getReserveEquipById(id, typeCode);
    }

    @Override
    public void downTemplate(HttpServletResponse response) {
        Workbook workbook = new HSSFWorkbook();
        Sheet sheet = workbook.createSheet();
        Row row = sheet.createRow(0);
        for (int i = 0; i < docxTitle.length; i++) {
            Cell cell = row.createCell(i);
            cell.setCellValue(docxTitle[i]);
        }
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode("电力设备批量导入模板.xls", "UTF-8"));
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            //throw new NormalException(e.getMessage());
        }
    }

    @Override
    public void uploadList(List<EquipmentExcelData> list, String orgCode) {
        if (!list.isEmpty()) {
            List<Equipment> equipmentList = new LinkedList<>();
            // 获取所有的区域编码
            Map<String, Object> res = (Map<String, Object>) iEquipManageFeign.getBuildingCodeKey();
            if (((int)res.get("status")) != 200) {
                throw new YeeException("解析位置编码失败");
            }
            Map<String, String> areaCodeIdMap = (Map<String, String>) res.getOrDefault("result", new HashMap<String, String>());
            // 获取所有存在的重点设备编码
            Set<String> equipCodeSet = impEquipMapper.getAllCode();
            for (int i = 0; i < list.size(); i++) {
                int row = i + 3;
                EquipmentExcelData x = list.get(i);
                String equipCode = x.getEquipCode();
                String equipName = x.getEquipName();
                String areaCode = x.getAreaCode();
                String position = x.getPosition();
                if (ValidationUtil.isEmpty(equipCode) || ValidationUtil.isEmpty(equipName) || ValidationUtil.isEmpty(areaCode)) {
                    throw new YeeException("错误行" + row + "：检查非空字段");
                }
                if (equipCodeSet.contains(equipCode.trim())) {
                    throw new YeeException("错误行" + row + "：重复的设备编号");
                }
                if (!areaCodeIdMap.containsKey(areaCode.trim())) {
                    throw new YeeException("错误行" + row + "：所属区域编号有误");
                }
                equipCodeSet.add(equipCode.trim());
                Equipment equipment = new Equipment();
                equipment.setName(equipName.trim());
                equipment.setCode(equipCode.trim());
                equipment.setRiskSourceId(Long.valueOf(areaCodeIdMap.get(areaCode.trim())));
                if (!ValidationUtil.isEmpty(position)) {
                    equipment.setAddress(position);
                }
                equipment.setIsIndoor(false);
                equipment.setOrgCode(orgCode);
                equipmentList.add(equipment);
            }
            iEquipmentDao.saveAll(equipmentList);
        }
    }

}
