package fr.insa.clavardator;

import fr.insa.clavardator.client.db.DatabaseController;
import fr.insa.clavardator.lib.message.Message;
import fr.insa.clavardator.lib.users.UserInformation;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.time.Duration;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

import static org.junit.jupiter.api.Assertions.*;

public class DatabaseTest {
	private final DatabaseController db = new DatabaseController(true);

	@Test
	void testDB() {
		assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
			CountDownLatch latch1 = new CountDownLatch(1);
			db.resetTables(latch1::countDown, Assertions::fail);
			latch1.await();

			CountDownLatch latch2 = new CountDownLatch(2);
			db.getAllUsers(users -> {
				assertEquals(0, users.size());
				latch2.countDown();
			}, Assertions::fail);

			db.getChatHistory(new UserInformation("1", "Yohan"),
					new UserInformation("0", "Arnaud"), new Date(0), new Date(), history -> {
						assertEquals(history.size(), 0);
						latch2.countDown();
					}, Assertions::fail);
			latch2.await();

			CountDownLatch latch8 = new CountDownLatch(1);
			db.addUser(new UserInformation("3", null), latch8::countDown, Assertions::fail);
			latch8.await();


			CountDownLatch latch3 = new CountDownLatch(5);
			db.addMessage(new Message(new UserInformation("1", "Yohan"), new UserInformation("2", "Arnaud"),
					new Date(1609843556860L), "Coucou Arnaud !"), latch3::countDown, Assertions::fail);
			db.addMessage(new Message(new UserInformation("2", "Arnaud"), new UserInformation("1", "Yohan"),
					new Date(1609843556861L), "Coucou Yohan !"), latch3::countDown, Assertions::fail);
			db.addMessage(new Message(new UserInformation("1", "Yohan"), new UserInformation("2", "Arnaud"),
					new Date(1609843556862L), "Ça va ?"), latch3::countDown, Assertions::fail);
			db.addMessage(new Message(new UserInformation("2", "Arnaud"), new UserInformation("1", "Yohan"),
					new Date(1609843556863L), "Ouais et toi ?"), latch3::countDown, Assertions::fail);
			db.addMessage(new Message(new UserInformation("1", "Yohan"), new UserInformation("2", "Arnaud"),
					new Date(1609843556864L), "Super !"), latch3::countDown, Assertions::fail);
			latch3.await();

			CountDownLatch latch4 = new CountDownLatch(2);
			db.getAllUsers(users -> {
				assertEquals(3, users.size());
				assertEquals("3", users.get(0).getId());
				assertEquals("1", users.get(1).getId());
				assertEquals("2", users.get(2).getId());
				assertNull(users.get(0).getUsername());
				assertEquals("Yohan", users.get(1).getUsername());
				assertEquals("Arnaud", users.get(2).getUsername());
				latch4.countDown();
			}, Assertions::fail);

			db.getChatHistory(new UserInformation("1", "Yohan"),
					new UserInformation("2", "Arnaud"), new Date(0), new Date(), history -> {
						assertEquals(5, history.size());
						assertEquals("Coucou Arnaud !", history.get(0).getText());
						assertEquals("1", history.get(0).getSender().id);
						assertEquals("2", history.get(0).getRecipient().id);
						assertEquals("Yohan", history.get(0).getSender().getUsername());
						assertEquals("Arnaud", history.get(0).getRecipient().getUsername());

						assertEquals("Ouais et toi ?", history.get(3).getText());
						assertEquals("2", history.get(3).getSender().id);
						assertEquals("1", history.get(3).getRecipient().id);
						assertEquals("Arnaud", history.get(3).getSender().getUsername());
						assertEquals("Yohan", history.get(3).getRecipient().getUsername());
						latch4.countDown();
					}, Assertions::fail);
			latch4.await();

			CountDownLatch latch5 = new CountDownLatch(1);
			db.updateUsername(new UserInformation("2", "Toto"), latch5::countDown, Assertions::fail);
			latch5.await();

			CountDownLatch latch7 = new CountDownLatch(1);
			db.resetTables(latch7::countDown, Assertions::fail);
			latch7.await();

			db.close();
		});
	}


}
