package com.izouma.zhirongip.service.supply;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.izouma.zhirongip.domain.Information;
import com.izouma.zhirongip.domain.Setting;
import com.izouma.zhirongip.domain.supply.TechnicalManager;
import com.izouma.zhirongip.dto.PageQuery;
import com.izouma.zhirongip.enums.ApplyStatus;
import com.izouma.zhirongip.exception.BusinessException;
import com.izouma.zhirongip.repo.InformationRepo;
import com.izouma.zhirongip.repo.SettingRepo;
import com.izouma.zhirongip.repo.supply.TechnicalManagerRepo;
import com.izouma.zhirongip.utils.JpaUtils;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class TechnicalManagerService {

    private final TechnicalManagerRepo technicalManagerRepo;
    private final SettingRepo          settingRepo;
    private final InformationRepo      informationRepo;

    public Page<TechnicalManager> all1(PageQuery pageQuery) {
        return technicalManagerRepo.findAll(JpaUtils.toSpecification(pageQuery, TechnicalManager.class), JpaUtils.toPageRequest(pageQuery));
    }

    public Page<TechnicalManager> all(PageQuery pageQuery, Long field) {
        Map<Long, String> settingMap = settingRepo.findAllByFlag(1)
                .stream()
                .collect(Collectors.toMap(Setting::getId, Setting::getName));

        return technicalManagerRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> and = JpaUtils.toPredicates(pageQuery, TechnicalManager.class, root, criteriaQuery, criteriaBuilder);
                    if (ObjectUtil.isNotNull(field)) {
                        Expression<Long> function = criteriaBuilder.function("FIND_IN_SET", Long.class, criteriaBuilder.literal(field), root
                                .get("field"));
                        and.add(criteriaBuilder.greaterThan(function, 0L));
                    }

                    return criteriaBuilder.and(and.toArray(new Predicate[0]));
                }), JpaUtils.toPageRequest(pageQuery))
                .map(manager -> {
                    manager.setFieldName(manager.getField()
                            .stream()
                            .map(settingMap::get)
                            .collect(Collectors.toList()));
                    return manager;
                });
    }


    public TechnicalManager get(Long id) {

        Map<Long, String> settingMap = settingRepo.findAllByFlag(1)
                .stream()
                .collect(Collectors.toMap(Setting::getId, Setting::getName));
        TechnicalManager technicalManager = technicalManagerRepo.findById(id).orElseThrow(new BusinessException("无记录"));
        technicalManager.setFieldName(technicalManager.getField()
                .stream()
                .map(settingMap::get)
                .collect(Collectors.toList()));

        return technicalManager;
    }

    /*
    推荐
     */
    public Page<TechnicalManager> recommend(Long id) {
        TechnicalManager manager = technicalManagerRepo.findById(id).orElseThrow(new BusinessException("无记录"));
        List<Long> field = manager.getField();

        if (CollUtil.isEmpty(field)) {
            return null;
        }

        Map<Long, String> settingMap = settingRepo.findAllByFlag(1)
                .stream()
                .collect(Collectors.toMap(Setting::getId, Setting::getName));

        Pageable limit = PageRequest.of(0, 3);
        return technicalManagerRepo.findAll((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> and = new ArrayList<>();
            and.add(criteriaBuilder.equal(root.get("isExpert"), manager.isExpert()));
            and.add(criteriaBuilder.or(field.stream()
                    .map(fi -> criteriaBuilder.function("FIND_IN_SET", Long.class,
                            criteriaBuilder.literal(fi), root.get("field")))
                    .map(findInSetFun -> criteriaBuilder.greaterThan(findInSetFun, 0L))
                    .toArray(Predicate[]::new)));
            and.add(criteriaBuilder.notEqual(root.get("id"), id));
            return criteriaBuilder.and(and.toArray(new Predicate[0]));
        }, limit).map(manager1 -> {
            manager1.setFieldName(manager1.getField()
                    .stream()
                    .map(settingMap::get)
                    .collect(Collectors.toList()));
            return manager1;
        });
    }

    public void audit(Long id, boolean pass, String remark) {
        TechnicalManager record = technicalManagerRepo.findById(id).orElseThrow(new BusinessException("无记录"));

        Information information = Information.builder()
                .receiveUserId(record.getUserId())
                .isRead(false)
                .build();

        if (pass) {
            record.setStatus(ApplyStatus.PASS);
            technicalManagerRepo.save(record);

            information.setContent("您发布的供给侧："+record.getName()+"已通过审核！");
            informationRepo.save(information);
            return;
        }
        record.setStatus(ApplyStatus.DENY);
        technicalManagerRepo.save(record);

        information.setContent("您发布的的供给侧："+record.getName()+"未通过审核，原因为：" + remark);
        informationRepo.save(information);
    }
}
