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

import cz.muni.fi.pa165.core.house.HouseRepository;
import cz.muni.fi.pa165.core.smartmeter.SmartMeter;
import cz.muni.fi.pa165.core.smartmeter.SmartMeterRepository;
import cz.muni.fi.pa165.core.user.UserRepository;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.util.regex.Pattern;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(SpringExtension.class)
@DataJpaTest
public class MetricsRepositoryTest {
	@Autowired
	private TestEntityManager entityManager;
	@Autowired
	private HouseRepository houseRepository;
	@Autowired
	private SmartMeterRepository smartMeterRepository;
	@Autowired
	private UserRepository userRepository;

	@Autowired
	private MetricsRepository metricsRepository;

	@Test
	public void createTesting() {
		String metrics = entityManager.persistAndGetId(new Metrics()).toString();
		// Regular expression to match UUID format
		Pattern uuidPattern = Pattern.compile(
				"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
				Pattern.CASE_INSENSITIVE);
		// Check if the string matches the UUID format
		boolean isUUID = uuidPattern.matcher(metrics).matches();
		assertThat(isUUID).isTrue();
	}

	@Test
	public void shouldFindNoneIfRepositoryIsEmpty() {
		Iterable<Metrics> metrics = metricsRepository.findAll();
		assertThat(metrics).isEmpty();
	}

	@Test
	public void shouldStore() {
		Metrics metrics = helperRegister();

		assertThat(metrics).hasFieldOrPropertyWithValue("consumptionKWH", 123.0);
	}

	@Test
	public void shouldFindAll() {
		Metrics metrics = new Metrics();
		entityManager.persist(metrics);

		Metrics metrics1 = new Metrics();
		entityManager.persist(metrics1);

		Metrics metrics2 = new Metrics();
		entityManager.persist(metrics2);

		assertThat(metricsRepository.findAll()).hasSize(3).contains(metrics, metrics1, metrics2);
	}

	@Test
	public void shouldFindById() {
		Metrics metrics = new Metrics();
		entityManager.persist(metrics);

		Metrics metrics1 = new Metrics();
		entityManager.persist(metrics1);

		Metrics metrics2 = new Metrics();
		entityManager.persist(metrics2);

		Metrics found = metricsRepository.findById(metrics1.getId()).get();

		assertThat(found).isEqualTo(metrics1);

		found = metricsRepository.findById(metrics.getId()).get();

		assertThat(found).isEqualTo(metrics);
	}

	@Test
	public void shouldUpdateById() {
		Metrics metrics = new Metrics();
		entityManager.persist(metrics);

		Metrics metrics1 = new Metrics();
		entityManager.persist(metrics1);

		Metrics update = metricsRepository.findById(metrics.getId()).get();
		update.setConsumptionKWH(1133.0);
		metricsRepository.save(update);

		Metrics check = metricsRepository.findById(metrics.getId()).get();

		assertThat(check.getId()).isEqualTo(metrics.getId());
		assertThat(check.getConsumptionKWH()).isEqualTo(metrics.getConsumptionKWH());
	}

	@Test
	public void shouldDeleteById() {
		Metrics metrics = new Metrics();
		entityManager.persist(metrics);

		Metrics metrics1 = helperRegister();
		entityManager.persist(metrics1);

		metricsRepository.deleteById(metrics1.getId());

		assertThat(metricsRepository.findAll()).hasSize(1).contains(metrics);
		assertThat(metricsRepository.findAll()).hasSize(1).doesNotContain(metrics1);
	}

	@Test
	void shouldDeleteAll() {
		entityManager.persist(helperRegister());

		metricsRepository.deleteAll();

		assertThat(metricsRepository.findAll()).isEmpty();
	}

	private Metrics helperRegister() {
		SmartMeter m = SmartMeter.builder().name("sm01").build();
		smartMeterRepository.save(m);
		return metricsRepository.save(new Metrics(123.0, m));
	}
}

