package io.openems.edge.predictor.profileclusteringmodel.services;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.time.Clock;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;

import org.junit.Test;

import io.openems.common.types.ChannelAddress;
import io.openems.edge.timedata.test.DummyTimedata;

public class TrainingDataServiceTest {

	@Test
	public void testFetchSeriesForWindow_ShouldReturnCorrectSeries() throws Exception {
		var timedata = new DummyTimedata("timedata0");
		var clock = Clock.fixed(ZonedDateTime.parse("2025-07-10T00:00:00+02:00").toInstant(),
				ZoneId.of("Europe/Berlin"));
		var channelAddress = new ChannelAddress("_sum", "testChannel");

		// Add data for 10 days, but with missing values every other 15min
		for (int day = 0; day < 10; day++) {
			var dayStart = ZonedDateTime.now(clock).minusDays(day).truncatedTo(ChronoUnit.DAYS);
			for (int min = 0; min < 24 * 60; min += 15) {
				// Skip some values to simulate missing data
				if (min % 30 != 0) {
					timedata.add(dayStart.plusMinutes(min), channelAddress, day * 10 + min);
				}
			}
		}

		var sut = new TrainingDataService(timedata, () -> clock, channelAddress);

		var series = sut.fetchSeriesForWindow(7);

		// Should have 7 (days) * 96 (quarters) entries
		assertEquals(7 * (24 * 4), series.getValues().size());

		// First timestamp should be exactly 7 days ago, truncated to day
		var expectedStart = ZonedDateTime.now(clock).minusDays(7).truncatedTo(ChronoUnit.DAYS);
		assertEquals(expectedStart, series.getIndex().getFirst());

		// Check that there are missing (NaN) values
		long nanCount = series.getValues().stream().filter(v -> v.isNaN()).count();
		assertTrue(nanCount > 0);

		// Ensure timestamps are continuous with 15 minutes between each
		var timestamps = series.getIndex();
		for (int i = 1; i < timestamps.size(); i++) {
			assertEquals(15, ChronoUnit.MINUTES.between(timestamps.get(i - 1), timestamps.get(i)));
		}
	}
}
