package com.xydl.cac.service.impl;

import com.xydl.cac.entity.Unit;
import com.xydl.cac.entity.Warning;
import com.xydl.cac.exception.BusinessException;
import com.xydl.cac.model.ConditionModel;
import com.xydl.cac.repository.UnitRepository;
import com.xydl.cac.repository.WarningRepository;
import com.xydl.cac.service.WarningService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class WarningServiceImpl implements WarningService {

    @Resource
    WarningRepository repository;
    @Resource
    UnitRepository unitRepository;

    @Override
    public Page<Warning> list(ConditionModel condition) throws Exception {
        PageRequest request = PageRequest.of(condition.getPageNum() - 1, condition.getPageSize());
        Specification<Warning> specification = (root, query, builder) -> {
            Predicate predicate = builder.conjunction();
            if (condition.getId() != null) {
                predicate.getExpressions().add(builder.equal(root.get("sensorId"), condition.getId().toString()));
            }
            if (StringUtils.isNotBlank(condition.getState())) {
                predicate.getExpressions().add(builder.equal(root.get("state"), condition.getState()));
            }
            if (condition.getStartTime() != null) {
                predicate.getExpressions().add(builder.greaterThan(root.get("warnTime"), condition.getStartTime()));
            }
            if (condition.getEndTime() != null) {
                predicate.getExpressions().add(builder.lessThanOrEqualTo(root.get("warnTime"), condition.getEndTime()));
            }
            query.orderBy(builder.desc(root.get("warnTime")));
            return predicate;
        };
        Page<Warning> result = repository.findAll(specification, request);
        this.fillOtherNames(result.getContent());
        return result;
    }

    private void fillOtherNames(List<Warning> list) {
        List<Unit> unitList = unitRepository.findAll();
        for (Warning item : list) {
            for (Unit unit : unitList) {
                if (unit.getField().equals(item.getField())) {
                    item.setUnit(unit.getUnit());
                    break;
                }
            }
        }
    }

    @Override
    public List<Warning> listAll(ConditionModel condition) throws Exception {
        Specification<Warning> specification = (root, query, builder) -> {
            Predicate predicate = builder.conjunction();
            if (condition.getId() != null) {
                predicate.getExpressions().add(builder.equal(root.get("sensorId"), condition.getId().toString()));
            }
            if (StringUtils.isNotBlank(condition.getState())) {
                predicate.getExpressions().add(builder.equal(root.get("state"), condition.getState()));
            }
            if (condition.getStartTime() != null) {
                predicate.getExpressions().add(builder.greaterThan(root.get("warnTime"), condition.getStartTime()));
            }
            if (condition.getEndTime() != null) {
                predicate.getExpressions().add(builder.lessThanOrEqualTo(root.get("warnTime"), condition.getEndTime()));
            }
            query.orderBy(builder.desc(root.get("warnTime")));
            return predicate;
        };
        List<Warning> list = repository.findAll(specification);
        this.fillOtherNames(list);
        return list;
    }

    @Override
    public void updateState(Warning warning) throws Exception {
        Optional<Warning> byId = repository.findById(warning.getId());
        if (!byId.isPresent()) {
            throw new BusinessException("未找到该告警id=" + warning.getId());
        }
        Warning war = byId.get();
        war.setState(warning.getState());
        war.setProcessTime(new Date());
        repository.save(war);
    }

    @Override
    public void oneKeyUpdateState() {
        repository.updateWarningState("0", "1");
    }


}
