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

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.device.allot.repository.AllotBillDao;
import com.tykj.dev.device.allot.subject.domin.AllotBill;
import com.tykj.dev.device.destroy.entity.domain.DeviceDestroyBill;
import com.tykj.dev.device.library.service.DeviceLibraryService;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.device.library.subject.vo.DeviceLibrarySelectVo;
import com.tykj.dev.device.packing.repository.PackingLibraryDao;
import com.tykj.dev.device.packing.subject.domin.PackingLibrary;
import com.tykj.dev.device.sendback.repository.SendBackBillDetailDao;
import com.tykj.dev.device.sendback.subject.domin.SendBackBillDetail;
import com.tykj.dev.device.storage.repository.StorageBillDao;
import com.tykj.dev.device.storage.subject.domin.StorageBill;
import com.tykj.dev.device.user.subject.service.UserPublicService;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.device.destroy.repository.DeviceDestroyBillDao;
import com.tykj.dev.device.usereport.repository.DeviceUseReportDao;
import com.tykj.dev.device.usereport.service.DeviceUseReportService;
import com.tykj.dev.device.usereport.subject.domin.DeviceUseReport;
import com.tykj.dev.device.usereport.subject.vo.DeviceUseReportCreateVo;
import com.tykj.dev.device.usereport.subject.vo.DeviceUseReportSelectVo;
import com.tykj.dev.misc.utils.StringSplitUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author dengdiyi
 */
@Service
public class DeviceUseReportServiceImpl implements DeviceUseReportService {

    @Autowired
    private DeviceUseReportDao deviceUseReportDao;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private DeviceLibraryService deviceLibraryService;

    @Autowired
    private StorageBillDao storageBillDao;

    @Autowired
    private UserPublicService userPublicService;

    @Autowired
    private AllotBillDao allotBillDao;

    @Autowired
    private DeviceDestroyBillDao deviceDestroyBillDao;

    @Autowired
    private SendBackBillDetailDao sendBackBillDetailDao;

    @Autowired
    private PackingLibraryDao packingLibraryDao;

    @Override
    public DeviceUseReport addEntity(DeviceUseReport deviceUseReportEntity) {
        return deviceUseReportDao.save(deviceUseReportEntity);
    }

    @Override
    public Page<DeviceUseReport> getPage(DeviceUseReportSelectVo deviceUseReportSelectVo, Pageable pageable) {
        return deviceUseReportDao.findAll(getSelectSpecification(deviceUseReportSelectVo),deviceUseReportSelectVo.getPageable());
    }

    @Override
    public DeviceUseReport getOne(Integer id) {
        Optional<DeviceUseReport> deviceUseReportEntity = deviceUseReportDao.findById(id);
        return deviceUseReportEntity.orElse(null);
    }

    @Override
    public DeviceUseReport update(DeviceUseReport deviceUseReportEntity) {
        return deviceUseReportDao.save(deviceUseReportEntity);
    }

    @Override
    public DeviceUseReport createReport(DeviceUseReportCreateVo deviceUseReportCreateVo) {
        DeviceUseReport deviceUseReportEntity = new DeviceUseReport();
        deviceUseReportEntity.setUnit(userUtils.getCurrentUserUnitName());
        StringBuffer stringBuffer = new StringBuffer();
        //按照开始时间和结束时间设置标题
        Date date = deviceUseReportCreateVo.getStartTime();
        Date date2 = deviceUseReportCreateVo.getEndTime();
        Calendar calendar = Calendar.getInstance();
        Calendar calendar2 = Calendar.getInstance();
        calendar.setTime(date);
        calendar2.setTime(date2);
        stringBuffer.append(calendar.get(Calendar.YEAR)).append("年");
        stringBuffer.append(calendar.get(Calendar.MONTH) + 1).append("月");
        stringBuffer.append(calendar.get(Calendar.DAY_OF_MONTH)).append("日");
        stringBuffer.append("至");
        stringBuffer.append(calendar2.get(Calendar.YEAR)).append("年");
        stringBuffer.append(calendar2.get(Calendar.MONTH) + 1).append("月");
        stringBuffer.append(calendar2.get(Calendar.DAY_OF_MONTH)).append("日");
        stringBuffer.append("使用情况报告");
        deviceUseReportEntity.setTitle(stringBuffer.toString());
        //获取所属当前单位的所有装备
        DeviceLibrarySelectVo deviceLibrarySelectVo = new DeviceLibrarySelectVo();
        deviceLibrarySelectVo.setSize(Integer.MAX_VALUE);
        List<DeviceLibrary> deviceLibraryEntities = deviceLibraryService.getPage(deviceLibrarySelectVo,deviceLibrarySelectVo.getPageable()).getContent();
        int num = deviceLibraryEntities.size();
        int inLibraryNum = 0;
        int repairNum = 0;
        int destoryNum=0;
        int allotNum = 0;
        int sendBackNum = 0;
        int packingNum = 0;
        int retiredNum = 0;
        //筛选出日期范围内所有入库账单
        List<StorageBill> storageBillEntities = storageBillDao.findAll().stream()
                .filter(storageBillEntity -> storageBillEntity.getStorageStatus()==2&&userUtils.getCurrentUserUnitName().equals(userPublicService.findUnitsNameByUserId(storageBillEntity.getReceiveUseraId()))&&storageBillEntity.getUpdateTime().after(date)&&storageBillEntity.getUpdateTime().before(date2))
                .collect(Collectors.toList());
        //累加入库数量
        if (storageBillEntities.size()>0){
            for (StorageBill s:storageBillEntities) {
                inLibraryNum = inLibraryNum + s.getStoragedCount();
            }
        }
        //配发状态list
        List<Integer> allotStatusList = new ArrayList<>();
        allotStatusList.add(2);
        allotStatusList.add(3);
        allotStatusList.add(5);
        //筛选出接收配发装备的账单
        List<AllotBill> allotBillEntities = allotBillDao.findAll().stream()
                .filter(allotBillEntity -> allotBillEntity.getAllotStatus()==5&&userUtils.getCurrentUserUnitName().equals(userPublicService.findUnitsNameByUserId(allotBillEntity.getReceiveUseraId()))&&allotBillEntity.getReceiveTime().after(date)&&allotBillEntity.getReceiveTime().before(date2))
                .collect(Collectors.toList());
        //筛选出配发给其它单位的账单
        List<AllotBill> allotBillEntities2 = allotBillDao.findAll().stream()
                .filter(allotBillEntity -> allotStatusList.contains(allotBillEntity.getAllotStatus())&&userUtils.getCurrentUserUnitName().equals(userPublicService.findUnitsNameByUserId(allotBillEntity.getSendUseraId()))&&allotBillEntity.getSendTime().after(date)&&allotBillEntity.getSendTime().before(date2))
                .collect(Collectors.toList());
        //累加入库数量
        if (allotBillEntities.size()>0){
            for (AllotBill s:allotBillEntities) {
                inLibraryNum = inLibraryNum + s.getReceiveCount();
            }
        }
        //累加配发数量
        if (allotBillEntities2.size()>0){
            for (AllotBill s:allotBillEntities) {
                allotNum = allotNum + s.getAllotedCount();
            }
        }
        //省级才能销毁,列装,退装
        if (userUtils.getCurrentUnitLevel()==1){
            //筛选出在日期范围内的销毁单
            List<DeviceDestroyBill> deviceDestoryBillEntities = deviceDestroyBillDao.findAll().stream()
                    .filter(deviceDestoryBillEntity -> deviceDestoryBillEntity.getDestroyStatus()==2&&deviceDestoryBillEntity.getDestroyTime().after(date)&&deviceDestoryBillEntity.getDestroyTime().before(date2))
                    .collect(Collectors.toList());
            //累加销毁数量
            if (deviceDestoryBillEntities.size()>0){
                for (DeviceDestroyBill s:deviceDestoryBillEntities) {
                    List<Integer> list = StringSplitUtil.split(s.getDestroyDeviceDetail());
                    destoryNum = destoryNum + list.size();
                }
            }
            //筛选列装
            List<PackingLibrary> packingLibraryEntities = packingLibraryDao.findAll().stream()
                    .filter(packingLibraryEntity -> packingLibraryEntity.getPackingStatus()==2&&packingLibraryEntity.getCreateTime().after(date)&&packingLibraryEntity.getCreateTime().before(date2)&&packingLibraryEntity.getIsPart()==0)
                    .collect(Collectors.toList());
            //筛选退装
            List<PackingLibrary> packingLibraryEntities2 = packingLibraryDao.findAll().stream()
                    .filter(packingLibraryEntity -> packingLibraryEntity.getPackingStatus()==3&&packingLibraryEntity.getExitTime().after(date)&&packingLibraryEntity.getExitTime().before(date2)&&packingLibraryEntity.getIsPart()==0)
                    .collect(Collectors.toList());
            //添加列装数量
            if (packingLibraryEntities.size()>0){
                packingNum = packingNum + packingLibraryEntities.size();
            }
            //添加退装数量
            if (packingLibraryEntities2.size()>0){
                retiredNum = retiredNum + packingLibraryEntities2.size();
            }
        }
        //清退状态筛选list
        List<Integer> sendBackStatusList = new ArrayList<>();
        sendBackStatusList.add(3);
        sendBackStatusList.add(4);
        sendBackStatusList.add(6);
        //筛选出清退账单
        List<SendBackBillDetail> sendBackBillDetailEntities = sendBackBillDetailDao.findAll().stream()
                .filter(sendBackBillDetailEntity -> sendBackStatusList.contains(sendBackBillDetailEntity.getSendBackStatus())&&sendBackBillDetailEntity.getSendUnit().equals(userUtils.getCurrentUserUnitName())&&sendBackBillDetailEntity.getSendTime().after(date)&&sendBackBillDetailEntity.getSendTime().before(date2))
                .collect(Collectors.toList());
        //累加清退数量
        if (sendBackBillDetailEntities.size()>0){
            for (SendBackBillDetail s:sendBackBillDetailEntities) {
                sendBackNum = sendBackNum + s.getSendedCount();
            }
        }
        // ToDo 维修数量
        //拼接组合字段
        deviceUseReportEntity.setReportDetail(num+"x"+inLibraryNum+"x"+repairNum+"x"+allotNum+"x"+sendBackNum+"x"+destoryNum+"x"+packingNum+"x"+retiredNum+"x");
        return deviceUseReportDao.save(deviceUseReportEntity);
    }

    @Override
    public void delete(Integer id) {
        deviceUseReportDao.deleteById(id);
    }

    private Specification<DeviceUseReport> getSelectSpecification(DeviceUseReportSelectVo deviceUseReportSelectVo){
        PredicateBuilder<DeviceUseReport> predicateBuilder = Specifications.and();
        if (deviceUseReportSelectVo!=null) {
            if (deviceUseReportSelectVo.getContent() != null) {
                Class<DeviceUseReport> deviceUseReportEntityClass = DeviceUseReport.class;
                Field[] declaredFields = deviceUseReportEntityClass.getDeclaredFields();
                PredicateBuilder<DeviceUseReport> p = Specifications.or();
                for (Field field : declaredFields) {
                    if (field.getType().equals(String.class)&&field.getAnnotation(Transient.class)==null) {
                        p.like(field.getName(), "%" + deviceUseReportSelectVo.getContent() + "%");
                    }
                }
                predicateBuilder.predicate(p.build());
            }
            if (deviceUseReportSelectVo.getStartTime() != null) {
                predicateBuilder.gt("createTime", deviceUseReportSelectVo.getStartTime());
            }
            if (deviceUseReportSelectVo.getEndTime() != null) {
                predicateBuilder.lt("updateTime", deviceUseReportSelectVo.getEndTime());
            }
        }
        return predicateBuilder.build();
    }
}
