package routines;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.text.ParseException;
import java.util.Date;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class LcagFileToolsTest {
	@BeforeAll
	static void setUpBeforeClass() throws Exception {
	}

	@Test
	void testReadTextFile() throws IOException {
		String result = LcagFileTools.readTextFile("src/test/resources/TestFile.xml");

		assertTrue(result != null && result.length() > 60);
	}

	@Test
	void testGetFileTimestampAsString() {
		String fileName = "2021-05-05_15-24-49-290Z_SomeFile.xml";
		String result = LcagFileTools.getFileTimestampAsString(fileName);

		assertEquals("2021-05-05_15-24-49-290Z", result);

		fileName = "input.xml";
		result = LcagFileTools.getFileTimestampAsString(fileName);
		assertNull(result);

		assertThrows(IllegalArgumentException.class, () -> {
			LcagFileTools.getFileTimestamp(null);
		}, "IllegalArgumentException expected if no filename given");
	}

	@Test
	void testGetFileTimestamp() {
		String fileName = "2021-05-05_15-24-49-290Z_SomeFile.xml";
		Date result = LcagFileTools.getFileTimestamp(fileName);
		String resultStr = LcagDateTime.MDM_FILE_TIMESTAMP_FORMAT.format(result);
		assertEquals("2021-05-05_15-24-49-290Z", resultStr);

		fileName = "input.xml";
		result = LcagFileTools.getFileTimestamp(fileName);
		assertNull(result);

		assertThrows(IllegalArgumentException.class, () -> {
			LcagFileTools.getFileTimestamp(null);
		}, "IllegalArgumentException expected if no filename given");
	}

	@Test
	void testCreateTimestampedFileName() throws ParseException {
		String result, expected;

		// Test 1: Function should be null safe
		result = LcagFileTools.createTimestampedFileName(null);
		assertTrue(result.endsWith("null"), "Function should be null safe");

		// Test 2: Function getFileTimestampAsString should be the inverse
		result = LcagFileTools.createTimestampedFileName("SomeFile.xml");
		String ts = LcagFileTools.getFileTimestampAsString(result);
		assertTrue(result.startsWith(ts), "Function getFileTimestampAsString should be the inverse of this function");

		Date d = LcagDateTime.MDM_FILE_TIMESTAMP_FORMAT.parse(ts);
		assertNotNull(d);

		// Test 3: return only file name in case a file path is given
		result = LcagFileTools.createTimestampedFileName("C:/A/B/C/SomeFile.xml");
		ts = LcagFileTools.getFileTimestampAsString(result);
		expected = ts + "_SomeFile.xml";

		assertEquals(expected, result, "File path should be cut to file name before adding the timestamp");

		d = LcagDateTime.MDM_FILE_TIMESTAMP_FORMAT.parse(ts);
		assertNotNull(d);

	}

	@Test
	void testGetFileNamePrefix() {
		Date aDate;
		String fileName = "2021-05-05_15-24-49-290Z_SomeFile.xml";
		String result = LcagFileTools.getFileNamePrefix(fileName);

		assertEquals("2021-05-05_15-24-49-290Z", result, "Should support old format (without numbering)");

		fileName = "2021-05-05_15-24-49-290Z-x12345_SomeFile.xml";
		result = LcagFileTools.getFileNamePrefix(fileName);
		assertEquals("2021-05-05_15-24-49-290Z-x12345_", result, "Should support new format (with numbering)");

		aDate = LcagFileTools.getFileTimestamp(fileName);
		assertNotNull(aDate, "Should be able extract a Timestamp from a file name with prefix");

		fileName = "input.xml";
		result = LcagFileTools.getFileNamePrefix(fileName);
		assertEquals("", result, "If there is no prefix, the result should be the empty string");
	}

	@Test
	void testCreatePrefixedFileName() throws ParseException {
		String result;
		Date d = new Date();

		result = LcagFileTools.createPrefixedFileName(null, d, 1);
		assertTrue(result.endsWith("null"), "Function should be null safe");

		result = LcagFileTools.createPrefixedFileName("SomeFile.xml", d, 0);
		String ts = LcagFileTools.getFileNamePrefix(result);
		assertTrue(result.startsWith(ts), "Function getFileNamePrefix should be the inverse of this function");
	}
}
