package com.tykj.dev.device.sendback.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.config.base.FileName;
import com.tykj.dev.device.file.entity.FileRet;
import com.tykj.dev.device.file.service.FilesUtil;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.device.library.subject.vo.ScriptSaveVo;
import com.tykj.dev.device.sendback.entity.domain.DeviceRepelDetail;
import com.tykj.dev.device.sendback.entity.vo.RepelDetailSelectVo;
import com.tykj.dev.device.sendback.repository.DeviceRepelDetailDao;
import com.tykj.dev.device.sendback.service.DeviceRepelDetailService;
import com.tykj.dev.misc.exception.ApiException;
import com.tykj.dev.misc.utils.JacksonUtil;
import com.tykj.dev.misc.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

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

/**
 * @author zjm
 * @version 1.0.0
 * @ClassName DeviceRepelDetailServiceImpl.java
 * @Description 清退业务详情逻辑层 每一次出入库生成一条业务
 * @createTime 2021年01月07日 09:52:00
 */
@Service
@Slf4j
public class DeviceRepelDetailServiceImpl implements DeviceRepelDetailService {
    @Autowired
    DeviceRepelDetailDao deviceRepelDetailDao;

    @Autowired
    DeviceLibraryDao deviceLibraryDao;

    @Override
    public DeviceRepelDetail saveDeviceRepelDetail(DeviceRepelDetail deviceRepelDetail) {
        log.info("[清退] 详情添加成功");
        return deviceRepelDetailDao.save(deviceRepelDetail);
    }

    @Override
    public DeviceRepelDetail findDeviceRepelDetail(Integer repelDetailId) {
        Optional<DeviceRepelDetail> optional = deviceRepelDetailDao.findById(repelDetailId);
        if (optional.isPresent()){
            DeviceRepelDetail deviceRepelDetail=optional.get();
            deviceRepelDetail.setDeviceLibraryEntities(findInvoleDevice(deviceRepelDetail.getDeviceIds()));
            deviceRepelDetail.setBillFiles(FilesUtil.stringFileToList(deviceRepelDetail.getBillFile()));
            deviceRepelDetail.setOutboundFiles(FilesUtil.stringFileToList(deviceRepelDetail.getOutboundFile()));
            deviceRepelDetail.setInFiles(FilesUtil.stringFileToList(deviceRepelDetail.getInFile()));
            deviceRepelDetail.setApplyFileList(FilesUtil.stringFileToList(deviceRepelDetail.getApplyFiles()));
            deviceRepelDetail.setReplyFileList(FilesUtil.stringFileToList(deviceRepelDetail.getReplyFiles()));
            return deviceRepelDetail;
        }else {
            log.info("[清退] 详情查看错误，id没有找到{}",repelDetailId);
            throw new ApiException(ResponseEntity.status(500).body("清退详情id没有找到:"+repelDetailId));
        }
    }

    @Override
    public DeviceRepelDetail findDeviceRepelDetailNoDev(Integer repelDetailId) {
        Optional<DeviceRepelDetail> optional = deviceRepelDetailDao.findById(repelDetailId);
        if (optional.isPresent()){
            return optional.get();
        }else {
            log.info("[清退] 详情查看错误，id没有找到{}",repelDetailId);
            throw new ApiException(ResponseEntity.status(500).body("清退详情id没有找到:"+repelDetailId));
        }
    }

    @Override
    public List<DeviceRepelDetail> findAll() {
        return deviceRepelDetailDao.findAll();
    }

    @Override
    public List<Integer> findYearAndUnitToDeviceList(Date time,Date endTime,Integer unitId) {
        Set<Integer> libraries=new HashSet<>();
        deviceRepelDetailDao.findAllBySendTimeBetweenAndSendUnitIdAndRepelStatus(time,endTime,unitId,2).forEach(
           deviceRepelDetail -> libraries.addAll(StringUtils.stringToList(deviceRepelDetail.getDeviceIds()))
        );
        return  new ArrayList<>(libraries);
    }

    @Override
    public List<DeviceRepelDetail> findUnitIdSendOrReceive(Integer unitId) {
        return deviceRepelDetailDao.findAllBySendUnitIdOrReceiveUnitId(unitId);
    }

    @Override
    public List<DeviceRepelDetail> findIdsReceiptUnits(List<Integer> unitIds) {
        return deviceRepelDetailDao.findAllByReceiveUnitIdIn(unitIds);
    }

    @Override
    public Page<DeviceRepelDetail> findPageDeviceRepelDetail(RepelDetailSelectVo repelDetailSelectVo) {
        return deviceRepelDetailDao.findAll(getFindRetiredSpecification(repelDetailSelectVo),repelDetailSelectVo.getPageable()).map(deviceRepelDetail -> {
            if (deviceRepelDetail.getScriptJson()!=null) {
                deviceRepelDetail.setScripts(JacksonUtil.readValue(deviceRepelDetail.getScriptJson(), new TypeReference<List<ScriptSaveVo>>() {
                }));
            }
            deviceRepelDetail.setBillFiles(FilesUtil.stringFileToList(deviceRepelDetail.getBillFile()));
            deviceRepelDetail.setOutboundFiles(FilesUtil.stringFileToList(deviceRepelDetail.getOutboundFile()));
            deviceRepelDetail.setInFiles(FilesUtil.stringFileToList(deviceRepelDetail.getInFile()));
            deviceRepelDetail.setReplyFileList(FilesUtil.stringFileToList(deviceRepelDetail.getReplyFiles()));
            deviceRepelDetail.setApplyFileList(FilesUtil.stringFileToList(deviceRepelDetail.getApplyFiles()));
            return deviceRepelDetail;
        });
    }

    @Override
    public Map<String, List<FileRet>> findByIdToFileMapList(Integer id) {
        Map<String, List<FileRet>> map=new HashMap<>();
        Optional<DeviceRepelDetail> optional = deviceRepelDetailDao.findById(id);
        if (optional.isPresent()){
            DeviceRepelDetail deviceRepelDetail=optional.get();
            map.put(FileName.APPLY.name,FilesUtil.stringFileToList(deviceRepelDetail.getApplyFiles()));
            map.put(FileName.RECEIPT.name,FilesUtil.stringFileToList(deviceRepelDetail.getOutboundFile()));
            map.put(FileName.SIGN.name,FilesUtil.stringFileToList(deviceRepelDetail.getBillFile()));
            map.put(FileName.REPLY.name,FilesUtil.stringFileToList(deviceRepelDetail.getReplyFiles()));
            return map;
        }else {
            log.info("[清退] 详情查看错误，id没有找到{}",id);
            throw new ApiException(ResponseEntity.status(500).body("清退详情id没有找到:"+id));
        }
    }

    @Override
    public int updateDeviceRepelDetailByIds(Integer deleteTag, List<Integer> ids) {

        return deviceRepelDetailDao.updateDeviceRepelDetailIsDelByIds(deleteTag,ids);
    }


    private Specification<DeviceRepelDetail> getFindRetiredSpecification(RepelDetailSelectVo repelDetailSelectVo) {
        PredicateBuilder<DeviceRepelDetail> predicateBuilder = Specifications.and();
        PredicateBuilder<DeviceRepelDetail> predicateBuilder1 = Specifications.or();

        predicateBuilder1.eq("sendUnitId",repelDetailSelectVo.getUnitId());
        predicateBuilder1.eq("receiveUnitId",repelDetailSelectVo.getUnitId());
        predicateBuilder.predicate(predicateBuilder1.build());
        if (repelDetailSelectVo.getStartTime() != null) {
            predicateBuilder.gt("createTime", repelDetailSelectVo.getStartTime());
        }
        if (repelDetailSelectVo.getEndTime() != null) {
            predicateBuilder.lt("createTime", repelDetailSelectVo.getEndTime());
        }
        predicateBuilder.eq("repelStatus", 2);
        predicateBuilder.eq("repelType",1,2);

        return predicateBuilder.build();

    }



    private List<DeviceLibrary> findInvoleDevice(String involeDevice){
        if (involeDevice!=null && !involeDevice.equals(",")&&!involeDevice.equals("")) {
        List<String> idStringList = Arrays.asList(involeDevice.split(","));
        List<String> idListString = idStringList.stream().filter(list2->!list2.equals("")).collect(Collectors.toList());
        List<Integer> devIds = idListString.stream().map(Integer::parseInt).collect(Collectors.toList());
        return deviceLibraryDao.getDeviceLibraryEntitiesByIdIn(devIds).stream().map(DeviceLibrary::setConfigName).collect(Collectors.toList());
        }else {
            return new ArrayList<>();
        }
        }
}
