package cz.muni.fi.pa165.core.smartmeter;

import cz.muni.fi.pa165.core.common.DomainService;
import cz.muni.fi.pa165.core.helpers.exceptions.EntityDeletionException;
import cz.muni.fi.pa165.core.metrics.Metrics;
import cz.muni.fi.pa165.core.metrics.MetricsRepository;
import cz.muni.fi.pa165.core.metrics.MetricsService;
import cz.muni.fi.pa165.core.metrics.Metrics;
import cz.muni.fi.pa165.core.metrics.MetricsService;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Optional;
import java.util.stream.Collectors;

import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;

@EnableScheduling
@Service
public class SmartMeterService extends DomainService<SmartMeter> {

  @Getter
  private final SmartMeterRepository repository;
  private final MetricsService metricsService;


  @Autowired
  public SmartMeterService(SmartMeterRepository smartMeterRepository, MetricsService metricsService) {
    this.repository = smartMeterRepository;
    this.metricsService = metricsService;
  }

  @Transactional(readOnly = true)
  public SmartMeter findByName(String name) {
    return getRepository()
            .findByName(name)
            .filter(entity -> entity.getDeletedAt() == null)
            .orElse(null);
  }

  @Override
  public void deleteAllById(String[] ids) throws EntityDeletionException {
    for (String id: ids) {
      Optional<SmartMeter> smartMeter = this.repository.findById(id);
      this.metricsService.deleteAllById(Optional.ofNullable(smartMeter.get().getMetricsList())
              .orElse(Collections.emptyList())
              .stream()
              .map(m -> m.getId()).toArray(String[]::new));
    }
    super.deleteAllById(ids);
  }

  @Transactional
  @Scheduled(cron = "0 * * * * *") //Create one metrics by minute
  @ConditionalOnProperty(name = "scheduler.enabled", matchIfMissing = true)
  public void createMetricsForActiveSmartMeters() {
    List<SmartMeter> smartMeterList = findAll();
    for (SmartMeter smartMeter : smartMeterList) {
      if (smartMeter.isActive()) {
        double value = Math.random() * 100;
        Metrics metrics = new Metrics(value, smartMeter);
        metricsService.create(metrics);
        smartMeter.getMetricsList().add(metrics);
        repository.save(smartMeter);
      }
    }
  }

}
