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

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.device.decommissioning.entity.DeviceDecommissioningDetail;
import com.tykj.dev.device.decommissioning.entity.vo.DecommissioningSelectVo;
import com.tykj.dev.device.decommissioning.entity.vo.PagingVo;
import com.tykj.dev.device.decommissioning.entity.vo.RepelManagementVo;
import com.tykj.dev.device.decommissioning.service.DeviceDecommissioningDetailService;
import com.tykj.dev.device.decommissioning.service.DeviceDecommissioningQueryService;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.device.task.service.TaskService;
import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.device.user.subject.entity.Units;
import com.tykj.dev.misc.base.BusinessEnum;
import com.tykj.dev.misc.base.DeviceLifeStatus;
import com.tykj.dev.misc.base.StatusEnum;
import com.tykj.dev.misc.exception.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.checkerframework.checker.units.qual.A;
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 javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zjm
 * @version 1.0.0
 * @ClassName DeviceDecommissioningQueryServiceImpl.java
 * @Description TODO
 * @createTime 2021年03月29日 16:39:00
 */
@Service
@Slf4j
@SuppressWarnings("ALL")
public class DeviceDecommissioningQueryServiceImpl implements DeviceDecommissioningQueryService {

    @Autowired
    TaskService taskService;

    @Autowired
    DeviceLibraryDao deviceLibraryDao;

    @Autowired
    DeviceDecommissioningDetailService deviceDecommissioningDetailService;

    @Override
    public List<TaskBto> findOutsideTheProvince() {
        List<TaskBto> taskBtoList;
        taskBtoList=taskService.findBillType(BusinessEnum.DECOMMISSIONING.id).stream().filter(taskBto -> !taskBto.getBillStatus().equals(StatusEnum.END.id)).collect(Collectors.toList());
        return taskBtoList;
    }

    @Override
    public List<TaskBto> findOutsideTheProvinceEnd() {
        List<TaskBto> taskBtoList;
        taskBtoList=taskService.findBillType(BusinessEnum.DECOMMISSIONING.id).stream().filter(taskBto -> taskBto.getBillStatus().equals(StatusEnum.END.id)).collect(Collectors.toList());
        return taskBtoList;
    }


    //装备有现成的接口直接调用
    @Override
    public PagingVo findRetired(RepelManagementVo repelManagementVo) {
        Page<DeviceLibrary> page= deviceLibraryDao.findAll(getFindRetiredSpecification(repelManagementVo),repelManagementVo.getPageable());
        return  PagingVo.builder()
                .data(page.getContent().stream().map(DeviceLibrary::setConfigName).collect(Collectors.toList())).page(repelManagementVo.getPage())
                .size(repelManagementVo.getSize()).total((int)page.getTotalElements()).build();
    }

    private Specification<DeviceLibrary> getFindRetiredSpecification(RepelManagementVo repelManagementVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(repelManagementVo);
//        List<Integer> leftStatus=new ArrayList<>();
//        leftStatus.add(com.tykj.dev.config.base.DeviceLifeStatus.RETIRED.id);
        predicateBuilder.in("lifeStatus", com.tykj.dev.config.base.DeviceLifeStatus.RETIRED.id);
        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());
            System.out.println(idListString);
            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<>();
        }
    }




    /**
     * 查询已清退装备列表
     */
    @Override
    public PagingVo retiredDeviceList(RepelManagementVo repelManagementVo) {
        Page<DeviceLibrary> page= deviceLibraryDao.findAll(getRetiredSpecification(repelManagementVo),repelManagementVo.getPageable());
        return PagingVo.builder()
                .data(page.getContent().stream().map(DeviceLibrary::setConfigName).collect(Collectors.toList())).page(repelManagementVo.getPage())
                .size(repelManagementVo.getSize()).total((int)page.getTotalElements()).build();
    }

    @Override
    public DeviceDecommissioningDetail findTaskIdDeviceDecommissioningDetail(Integer taskId) {
        TaskBto taskBto=taskService.get(taskId);
        return deviceDecommissioningDetailService.findDeviceDecommissioningDetail(taskBto.getBillId());
    }

    @Override
    public TaskBto findApplyIdToDecommissioningTask(Integer applyId) {
        DeviceDecommissioningDetail deviceDecommissioningDetail= deviceDecommissioningDetailService.findApplyId(applyId);
        if (deviceDecommissioningDetail==null){
            return null;
        }else {
            Optional<Task> billIdAndBusinessType = taskService.findBillIdAndBusinessType(deviceDecommissioningDetail.getId(), BusinessEnum.DECOMMISSIONING.id,StatusEnum.ARCHIVE.id);
            if (billIdAndBusinessType.isPresent()){
                TaskBto taskBto=billIdAndBusinessType.get().parse2Bto();
                return taskBto;
            }else {
                log.info("[退役] 根据申请id未查询退役任务 ：{}",applyId);
                return null;
//                throw new ApiException(ResponseEntity.status(500).body("[退役] 根据申请id未查询退役任务 ："+applyId));
            }
        }

    }

    @Override
    public Page<DeviceDecommissioningDetail> findPageDeviceDecommissioningDetail(DecommissioningSelectVo decommissioningSelectVo) {

        return deviceDecommissioningDetailService.findPageDeviceDecommissioningDetail(decommissioningSelectVo);
    }

    private Specification<DeviceLibrary> getRetiredSpecification(RepelManagementVo repelManagementVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(repelManagementVo);
        predicateBuilder.eq("lifeStatus", DeviceLifeStatus.RETIRE.id);
        return predicateBuilder.build();
    }


    /**
     * 查询待退役列表
     * @param repelManagementVo 条件对象
     * @return 退役对象
     */
    @Override
    public PagingVo toBeRetiredDeviceList(RepelManagementVo repelManagementVo) {
        Page<DeviceLibrary> page = deviceLibraryDao.findAll(getSelectSpecification(repelManagementVo),repelManagementVo.getPageable());
//        deviceLibraryDao.findAll(getSelectSpecification(repelManagementVo),repelManagementVo.getPageable())
//        deviceLibrarySelectVo.setLifeStatus(leftStatus);
        return PagingVo.builder()
                .data(page.getContent().stream().map(DeviceLibrary::setConfigName).collect(Collectors.toList())).page(repelManagementVo.getPage())
                .size(repelManagementVo.getSize()).total((int)page.getTotalElements()).build();
    }




    private Specification<DeviceLibrary> getSelectSpecification(RepelManagementVo repelManagementVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(repelManagementVo);
        //unitId为空，默认查询当前单位
//        List<Integer> leftStatus=new ArrayList<>();
//        leftStatus.add(DeviceLifeStatus.REPEL.id);
        predicateBuilder.eq("lifeStatus", DeviceLifeStatus.REPEL.id);
        predicateBuilder.eq("locationUnit", repelManagementVo.getUnitName());
        predicateBuilder.eq("ownUnit", repelManagementVo.getUnitName());
        return predicateBuilder.build();

    }


    private PredicateBuilder<DeviceLibrary> getPredicateBuilder(RepelManagementVo repelManagementVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        if (repelManagementVo != null) {
            if (repelManagementVo.getModel() != null) {
                predicateBuilder.eq("model", repelManagementVo.getModel());
            }
            if (repelManagementVo.getName() != null) {
                predicateBuilder.eq("name", repelManagementVo.getName());
            }
            if (repelManagementVo.getSecretLevel() != null) {
                predicateBuilder.eq("secretLevel", repelManagementVo.getSecretLevel());
            }
            if (repelManagementVo.getMatchingRange() != null) {
                predicateBuilder.eq("matchingRange", repelManagementVo.getMatchingRange());
            }
            if (repelManagementVo.getStorageType() != null) {
                predicateBuilder.eq("storageType", repelManagementVo.getStorageType());
            }
            if (repelManagementVo.getManageStatus() != null) {
                predicateBuilder.eq("manageStatus", repelManagementVo.getManageStatus());
            }
            if (repelManagementVo.getInvisibleRange() != null) {
                predicateBuilder.eq("invisibleRange", repelManagementVo.getInvisibleRange());
            }
            if (repelManagementVo.getTime()!=null){
                predicateBuilder.gt("updateTime",new Date(repelManagementVo.getTime()));
            }
            if (repelManagementVo.getEndTime()!=null){
                predicateBuilder.lt("updateTime",new Date(repelManagementVo.getEndTime()));
            }
            if (repelManagementVo.getContent() != null) {
                Class<DeviceLibrary> deviceLibraryEntity = DeviceLibrary.class;
                Field[] declaredFields = deviceLibraryEntity.getDeclaredFields();
                PredicateBuilder<DeviceLibrary> p = Specifications.or();
                for (Field field : declaredFields) {
                    if (field.getType().equals(String.class) && field.getAnnotation(Transient.class) == null) {
                        p.like(field.getName(), "%" + repelManagementVo.getContent() + "%");
                    }
                }
                predicateBuilder.predicate(p.build());
            }
        }
        return predicateBuilder;
    }


}
