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

import cz.muni.fi.pa165.core.house.HouseRepository;
import cz.muni.fi.pa165.core.smartmeter.SmartMeterRepository;
import cz.muni.fi.pa165.core.user.UserRepository;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
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.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.regex.Pattern;

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

@ExtendWith(SpringExtension.class)
@WithMockUser
@AutoConfigureMockMvc(addFilters = false)
@DataJpaTest
public class CompanyRepositoryTest {
	@Autowired
	private TestEntityManager entityManager;
	@Autowired
	private CompanyRepository companyRepository;
	@Autowired
	private HouseRepository houseRepository;
	@Autowired
	private SmartMeterRepository smartMeterRepository;
	@Autowired
	private UserRepository userRepository;

	@Test
	void createCompanyTesting() {
		String company = entityManager.persistAndGetId(Company.builder().name("Apple").build()).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(company).matches();
		assertThat(isUUID).isTrue();
	}

	@Test
	public void shouldFindNoneIfRepositoryIsEmpty() {
		Iterable<Company> companies = companyRepository.findAll();
		assertThat(companies).isEmpty();
	}

	@Test
	public void shouldStore() {
		Company company = helperRegister();

		assertThat(company).hasFieldOrPropertyWithValue("name", "Tesla");
	}

	@Test
	void shouldFindAll() {
		Company company = Company.builder().name("Apple").build();
		entityManager.persist(company);

		Company company1 = Company.builder().name("HP").build();
		entityManager.persist(company1);

		Company company2 = Company.builder().name("Acer").build();
		entityManager.persist(company2);

		assertThat(companyRepository.findAll()).hasSize(3).contains(company, company1, company2);
	}

	@Test
	void shouldFindById() {
		Company company = Company.builder().name("Apple").build();

		entityManager.persist(company);

		Company company1 = Company.builder().name("HP").build();
		entityManager.persist(company1);

		Company company2 = Company.builder().name("Acer").build();
		entityManager.persist(company2);

		Company found = companyRepository.findById(company2.getId()).get();

		assertThat(found).isEqualTo(company2);

		found = companyRepository.findById(company1.getId()).get();

		assertThat(found).isEqualTo(company1);
	}

	@Test
	void shouldUpdateById() {
		Company company = Company.builder().name("Apple").build();
		entityManager.persist(company);

		Company company1 = Company.builder().name("HP").build();
		entityManager.persist(company1);

		Company updateCompany = companyRepository.findById(company1.getId()).get();
		updateCompany.setName("Gorenje");
		companyRepository.save(updateCompany);

		Company check = companyRepository.findById(company1.getId()).get();

		assertThat(check.getId()).isEqualTo(company1.getId());
		assertThat(check.getName()).isEqualTo(company1.getName());
	}

	@Test
	void shouldDeleteById() {
		Company company = Company.builder().name("Apple").build();
		entityManager.persist(company);

		Company company1 = helperRegister();
		entityManager.persist(company1);

		companyRepository.deleteById(company1.getId());

		assertThat(companyRepository.findAll()).hasSize(1).contains(company);
		assertThat(companyRepository.findAll()).hasSize(1).doesNotContain(company1);
	}

	@Test
	void shouldDeleteAll() {
		entityManager.persist(Company.builder().name("Apple").build());
		entityManager.persist(helperRegister());

		companyRepository.deleteAll();

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

	private Company helperRegister() {
		return companyRepository.save(new Company("Tesla", new ArrayList<>(), new ArrayList<>(), new ArrayList<>()));
	}
}
