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

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.blockcha.subject.entity.BcHash;
import com.tykj.dev.blockcha.subject.service.BlockChainUtil;
import com.tykj.dev.config.TaskBeanConfig;
import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.train.dao.TrainThemeDao;
import com.tykj.dev.device.train.dao.TrainUserDao;
import com.tykj.dev.device.train.entity.TrainTheme;
import com.tykj.dev.device.train.entity.TrainUser;
import com.tykj.dev.device.train.entity.vo.*;
import com.tykj.dev.device.train.service.TrainTaskService;
import com.tykj.dev.device.train.service.TrainThemeService;
import com.tykj.dev.device.user.subject.service.MgrcertService;
import com.tykj.dev.device.user.subject.service.UserService;
import com.tykj.dev.misc.base.BusinessEnum;
import com.tykj.dev.misc.exception.ApiException;
import com.tykj.dev.misc.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
 * @author zjm
 * @version 1.0.0
 * @ClassName TrainServiceImpl.java
 * @Description 培训逻辑层
 * @createTime 2020年08月13日 15:25:00
 */
@Service
@Slf4j
public class TrainThemeServiceImpl implements TrainThemeService {

    @Autowired
    TrainThemeDao trainThemeDao;

    @Autowired
    MgrcertService mgrcertService;

    @Autowired
    UserService userService;
    @Autowired
    TrainTaskService trainTaskService;

    @Autowired
    TrainUserDao trainUserDao;
    @Autowired
    BlockChainUtil blockChainUtil;

    @Override
    public TrainTheme save(TrainTheme trainTheme) {
        TrainTheme trainTheme1 = trainThemeDao.save(trainTheme);
        CompletableFuture.runAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TrainTheme trainTheme2 = findById(trainTheme1.getTrainId());
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(trainTheme2));
            String recordId = bcText.getData().getRecordID();
            trainTheme2.setRecordId(recordId);
            trainThemeDao.save(trainTheme2);
        }, TaskBeanConfig.getThreadPoolTaskScheduler());
        return trainTheme1;
    }

    /**
     * @param trainThemes 异步上链
     */
    @Override
    @Async
    public void sendHash(List<TrainTheme> trainThemes) {
        trainThemes.forEach(trainTheme1 -> {
            BcHash bcHash=blockChainUtil.sendHash(1000,JacksonUtil.toJSon(trainTheme1));
            trainTheme1.setRecordId(bcHash.getData().getRecordID());
            trainThemeDao.save(trainTheme1);
        });
    }

    @Override
    public TrainTheme findById(Integer trainThemeId) {

        return trainThemeDao.findById(trainThemeId).get();
    }

    @Override
    public List<TrainTheme> findAllStatus(Integer status) {
        return trainThemeDao.findAllByTrainStatus(status);
    }

    @Override
    public ByTrainingPeople findByTrainingPeople(Integer trainThemeId, Integer userId) {
        TrainTheme trainTheme = trainThemeDao.findById(trainThemeId).get();
        ByTrainingPeople byTrainingPeople = trainTheme.toByTrainingPeople();
        TrainUser trainUser=trainUserDao.findByUserIdAndTrainId(userId,trainThemeId);
        List<TrainUser> trainUsers=trainUserDao.findAllByUnitsIdAndTrainId(trainUser.getUnitsId(),trainThemeId);
        trainUsers.forEach(
                trainUser1 -> trainUser1.setMgrcert(mgrcertService.findByUserId(trainUser1.getUserId()))
        );
        byTrainingPeople.setTrainUserList(trainUsers);
        return byTrainingPeople;
    }



    @Override
    public TrainRegistrationVo findRegistrationVo(Integer trainThemeId) {
        TrainTheme trainTheme = trainThemeDao.findById(trainThemeId).get();
        TrainRegistrationVo trainRegistrationVo = trainTheme.toTrainRegistrationVo();
        trainRegistrationVo.setSignUpUser(trainUserDao.findAllByIsSignUpAndTrainId(1,trainThemeId));
        trainRegistrationVo.setNoSignUpUser(trainUserDao.findAllByIsSignUpAndTrainId(2,trainThemeId));
        return trainRegistrationVo;
    }

    @Override
    public TrainTrainingVo findTrainTrainingVo(Integer trainThemeId) {
        TrainTheme trainTheme = trainThemeDao.findById(trainThemeId).get();
        TrainTrainingVo trainTrainingVo = trainTheme.toTrainTrainingVo();
        trainTrainingVo.setTrainUsers(trainUserDao.findAllByIsSignUpAndTrainId(1,trainThemeId));
        return trainTrainingVo;
    }

    @Override
    public TrainAuditVo findTrainAuditVo(Integer trainThemeId) {
        TrainTheme trainTheme = trainThemeDao.findById(trainThemeId).get();
        TrainAuditVo trainAuditVo = trainTheme.toTrainAuditVo();
        List<TrainUser> trainUsers= trainUserDao.findAllByIsSignUpAndTrainId(1,trainThemeId);
        trainUsers.forEach(trainUser -> {
            trainUser.setMgrcert(mgrcertService.findByUserId(trainUser.getUserId()));
        });
        trainAuditVo.setTrainUser(trainUsers);
        return trainAuditVo;
    }

    @Override
    public TrainTheme updateTrain(TrainUpdateVo trainUpdateVo) {
        TrainTheme trainTheme = trainThemeDao.findById(trainUpdateVo.getTrainId()).get();
        if (trainUpdateVo.getEndTime() != null) {
            trainTheme.setEndTime(trainUpdateVo.getEndTime());
        }
        if (trainUpdateVo.getSpeakerUserId() != null) {
            trainTheme.setSpeakerUserId(trainUpdateVo.getSpeakerUserId());
        }
        if (trainUpdateVo.getStartTime() != null) {
            trainTheme.setStartTime(trainUpdateVo.getStartTime());
        }
        if (trainUpdateVo.getTrainDataName() != null) {
            trainTheme.setTrainDataName(trainUpdateVo.getTrainDataName());
        }
        if (trainUpdateVo.getTrainDataUrl() != null) {
            trainTheme.setTrainDataUrl(trainUpdateVo.getTrainDataUrl());
        }
        if (trainUpdateVo.getTrainLocation() != null) {
            trainTheme.setTrainLocation(trainUpdateVo.getTrainLocation());
        }
        if (trainUpdateVo.getTrainSynopsis() != null) {
            trainTheme.setTrainSynopsis(trainUpdateVo.getTrainSynopsis());
        }
        TrainTheme trainTheme1 = trainThemeDao.save(trainTheme);
        CompletableFuture.runAsync(()->blockChainUtil.appendHash(JacksonUtil.toJSon(trainTheme1),trainTheme1.getRecordId()),TaskBeanConfig.getThreadPoolTaskScheduler());
        return trainTheme1;
    }

    @Override
    public TrainThemePage findTrainPageVo(ConditionsTrainVo conditionsTrainVo) {
        Pageable pageable = PageRequest.of(conditionsTrainVo.getPage(), conditionsTrainVo.getSize(), Sort.Direction.ASC, "trainTime");
        Page<TrainTheme> all = getContacts(conditionsTrainVo,pageable);

        List<TrainThemeVo> list = new ArrayList<>();
        all.getContent().forEach(
                trainTheme -> {
                    if (trainTheme!=null) {
                        TaskBto taskBto = trainTaskService.selectFatherIsNullAndBillidAndBillType(trainTheme.getTrainId(), BusinessEnum.TRAIN.id);
                        TrainThemeVo trainThemeVo = trainTheme.toTrainThemeVo();
                        trainThemeVo.setTaskId(taskBto.getId());
                        list.add(trainThemeVo);
                    }
                }
        );

        return TrainThemePage.builder()
                .data(list)
                .page(conditionsTrainVo.getPage())
                .size(conditionsTrainVo.getSize())
                .total((int) all.getTotalElements()).build();
    }

    @Override
    public TrainDetailsVo findSelectDetailsVo(Integer trainId) {
        Optional<TrainTheme> trainThemeOptional= trainThemeDao.findById(trainId);

        if (trainThemeOptional.isPresent()){
            TrainTheme trainTheme=trainThemeOptional.get();
            TrainDetailsVo trainDetailsVo=trainTheme.toTrainDetailsVo();
            List<TrainUser> trainUsers= trainUserDao.findAllByIsSignUpAndTrainId(1,trainId);
            trainUsers.forEach(trainUser -> {
                trainUser.setMgrcert(mgrcertService.findByUserId(trainUser.getUserId()));
            });
            trainDetailsVo.setTrainUsers(trainUsers);
        return trainDetailsVo;
        }else {
          throw new ApiException(ResponseEntity.ok("培训id没有查询到，请检查"));
        }

    }

    private Page<TrainTheme> getContacts(ConditionsTrainVo conditionsTrainVo, Pageable pageable) {
        PredicateBuilder<TrainTheme> predicateBuilder = Specifications.and();
        if (conditionsTrainVo.getEndTime() != null && conditionsTrainVo.getStatusTime() != null) {
            predicateBuilder.gt("startTime", conditionsTrainVo.getStatusTime());
            predicateBuilder.lt("endTime", conditionsTrainVo.getEndTime());
        }
        if (conditionsTrainVo.getDimName() != null) {
            Class<TrainTheme> trainThemeClass = TrainTheme.class;
            Field[] declaredFields = trainThemeClass.getDeclaredFields();
            PredicateBuilder<TrainTheme> p = Specifications.or();
            for (Field field : declaredFields) {
                if (field.getType().equals(String.class)) {
                    p.like(field.getName(), "%" + conditionsTrainVo.getDimName() + "%");
                }
            }
            predicateBuilder.predicate(p.build());
        }
        return trainThemeDao.findAll(predicateBuilder.build(), pageable);
    }


}
