package eu.dnetlib.data.mdstore.manager.controller;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Date;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import eu.dnetlib.data.mdstore.manager.exceptions.MDStoreManagerException;
import eu.dnetlib.data.mdstore.manager.utils.DatabaseUtils;
import eu.dnetlib.dhp.schema.mdstore.MDStoreVersion;
import eu.dnetlib.dhp.schema.mdstore.MDStoreWithInfo;

@Disabled
@SpringBootTest
class MDStoreControllerTest {

	@Autowired
	private MDStoreController controller;

	@Autowired
	private DatabaseUtils databaseUtils;

	@Test
	void testSimpleCreationAndDelete() throws MDStoreManagerException {

		final long now = new Date().getTime();

		final MDStoreWithInfo store = controller.createMDStore("oai_dc", "store", "native", "TEST REPO", "openaire____::1234", "openaire____::1234::oai");

		final String mdId = store.getId();
		final String firstVersion = store.getCurrentVersion();

		final long lastUpdate = store.getLastUpdate().getTime();

		assertTrue(mdId.length() > 0);
		assertTrue(firstVersion.length() > 0);
		assertTrue(lastUpdate > now);
		assertEquals("oai_dc", store.getFormat());
		assertEquals("store", store.getLayout());
		assertEquals("native", store.getInterpretation());
		assertEquals(1, store.getNumberOfVersions());
		assertEquals(0l, store.getSize());
		assertEquals("TEST REPO", store.getDatasourceName());
		assertEquals("openaire____::1234", store.getDatasourceId());
		assertEquals("openaire____::1234::oai", store.getApiId());

		final MDStoreWithInfo store2 = controller.getMdStore(mdId);

		assertEquals(store2.getId(), mdId);
		assertEquals(store2.getCurrentVersion(), firstVersion);
		assertEquals(store2.getLastUpdate().getTime(), lastUpdate);
		assertEquals(store2.getFormat(), store.getFormat());
		assertEquals(store2.getLayout(), store.getLayout());
		assertEquals(store2.getInterpretation(), store.getInterpretation());
		assertEquals(store2.getNumberOfVersions(), store.getNumberOfVersions());
		assertEquals(store2.getSize(), store.getSize());
		assertEquals(store2.getDatasourceName(), store.getDatasourceName());
		assertEquals(store2.getDatasourceId(), store.getDatasourceId());
		assertEquals(store2.getApiId(), store.getApiId());

		final StatusResponse res = controller.delete(mdId);
		assertEquals("DELETED", res.getStatus());

		try {
			controller.getMdStore(mdId);
			assertTrue(false);
		} catch (final MDStoreManagerException e) {
			assertTrue(true);
		}
	}

	@Test
	void testSimpleReading() throws MDStoreManagerException {

		final MDStoreWithInfo store = controller.createMDStore("oai_dc", "store", "native", "TEST REPO", "openaire____::1234", "openaire____::1234::oai");

		final String mdId = store.getId();
		final String firstVersion = store.getCurrentVersion();

		final MDStoreVersion v1 = controller.startReading(mdId);
		assertEquals(firstVersion, v1.getId());
		assertEquals(0l, v1.getSize());
		assertEquals(1, v1.getReadCount());

		final MDStoreVersion v2 = controller.startReading(mdId);
		assertEquals(firstVersion, v2.getId());
		assertEquals(0l, v2.getSize());
		assertEquals(2, v2.getReadCount());

		final MDStoreVersion v3 = controller.startReading(mdId);
		assertEquals(firstVersion, v3.getId());
		assertEquals(0l, v3.getSize());
		assertEquals(3, v3.getReadCount());

		final MDStoreVersion v4 = controller.endReading(v1.getId());
		assertEquals(firstVersion, v4.getId());
		assertEquals(0l, v4.getSize());
		assertEquals(2, v4.getReadCount());

		final MDStoreVersion v5 = controller.endReading(v2.getId());
		assertEquals(firstVersion, v5.getId());
		assertEquals(0l, v5.getSize());
		assertEquals(1, v5.getReadCount());

		final MDStoreVersion v6 = controller.endReading(v3.getId());
		assertEquals(firstVersion, v6.getId());
		assertEquals(0l, v6.getSize());
		assertEquals(0, v6.getReadCount());

		controller.delete(mdId);
	}

	@Test
	void testSimpleNewVersion() throws MDStoreManagerException {

		final MDStoreWithInfo store = controller.createMDStore("oai_dc", "store", "native", "TEST REPO", "openaire____::1234", "openaire____::1234::oai");

		final String mdId = store.getId();
		final String firstVersion = store.getCurrentVersion();

		final MDStoreVersion v1 = controller.prepareNewVersion(mdId);
		final MDStoreWithInfo md1 = controller.getMdStore(mdId);
		assertNotEquals(v1.getId(), md1.getCurrentVersion());
		assertEquals(firstVersion, md1.getCurrentVersion());
		assertEquals(0l, md1.getSize());

		final MDStoreVersion v2 = controller.commitVersion(v1.getId(), 1234l);
		final MDStoreWithInfo md2 = controller.getMdStore(mdId);
		assertNotEquals(v1.getId(), md1.getCurrentVersion());
		assertEquals(v1.getId(), md2.getCurrentVersion());
		assertEquals(v2.getId(), md2.getCurrentVersion());
		assertEquals(1234l, md2.getSize());

		controller.delete(mdId);
	}

	@Test
	void testNewVersions() throws MDStoreManagerException {

		final MDStoreWithInfo store = controller.createMDStore("oai_dc", "store", "native", "TEST REPO", "openaire____::1234", "openaire____::1234::oai");

		final String mdId = store.getId();

		final String v1 = controller.prepareNewVersion(mdId).getId();
		final String v2 = controller.prepareNewVersion(mdId).getId();
		final String v3 = controller.prepareNewVersion(mdId).getId();

		assertEquals(0, databaseUtils.listExpiredVersions().size());

		controller.commitVersion(v3, 1111l).getId();
		assertEquals(v3, controller.getMdStore(mdId).getCurrentVersion());
		assertEquals(1, databaseUtils.listExpiredVersions().size());

		controller.commitVersion(v1, 2222l).getId();
		assertEquals(v1, controller.getMdStore(mdId).getCurrentVersion());
		assertEquals(2, databaseUtils.listExpiredVersions().size());

		controller.commitVersion(v2, 3333l).getId();
		assertEquals(v2, controller.getMdStore(mdId).getCurrentVersion());
		assertEquals(3, databaseUtils.listExpiredVersions().size());

		controller.delete(mdId);
	}

	@Test
	void testNewVersionsAndReading() throws MDStoreManagerException {

		final MDStoreWithInfo store = controller.createMDStore("oai_dc", "store", "native", "TEST REPO", "openaire____::1234", "openaire____::1234::oai");

		final String mdId = store.getId();
		final String firstVersion = store.getCurrentVersion();

		final String vr1 = controller.startReading(mdId).getId();
		assertEquals(firstVersion, vr1);

		final String v1 = controller.prepareNewVersion(mdId).getId();

		final String vr2 = controller.startReading(mdId).getId();
		assertEquals(firstVersion, vr2);

		controller.commitVersion(v1, 1111l);

		final String vr3 = controller.startReading(mdId).getId();
		assertEquals(v1, vr3);

		assertEquals(0, databaseUtils.listExpiredVersions().size());
		controller.endReading(vr1);
		assertEquals(0, databaseUtils.listExpiredVersions().size());
		controller.endReading(vr3);
		assertEquals(0, databaseUtils.listExpiredVersions().size());
		controller.endReading(vr2);
		assertEquals(1, databaseUtils.listExpiredVersions().size());
		assertEquals(firstVersion, databaseUtils.listExpiredVersions().get(0));

		controller.delete(mdId);
	}

}
