package com.dedicatedcode.reitti.service.importer;

import com.dedicatedcode.reitti.config.RabbitMQConfig;
import com.dedicatedcode.reitti.event.LocationDataEvent;
import com.dedicatedcode.reitti.model.processing.DetectionParameter;
import com.dedicatedcode.reitti.model.processing.RecalculationState;
import com.dedicatedcode.reitti.model.security.User;
import com.dedicatedcode.reitti.service.ImportBatchProcessor;
import com.dedicatedcode.reitti.service.ImportStateHolder;
import com.dedicatedcode.reitti.service.VisitDetectionParametersService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;

import java.time.Instant;
import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;

class GoogleIOSTimelineImporterTest {

    @Test
    void shouldParseNewGoogleTakeOutFileFromIOS() {
        RabbitTemplate mock = mock(RabbitTemplate.class);
        VisitDetectionParametersService parametersService = mock(VisitDetectionParametersService.class);
        DetectionParameter config = new DetectionParameter(-1L,
                new DetectionParameter.VisitDetection(100, 5, 300, 300),
                new DetectionParameter.VisitMerging(24,300, 100),
                null, RecalculationState.DONE);
        when(parametersService.getCurrentConfiguration(any(), any(Instant.class))).thenReturn(config);

        GoogleIOSTimelineImporter importHandler = new GoogleIOSTimelineImporter(new ObjectMapper(), new ImportStateHolder(), new ImportBatchProcessor(mock, 100, 15), parametersService);
        User user = new User("test", "Test User");
        Map<String, Object> result = importHandler.importTimeline(getClass().getResourceAsStream("/data/google/timeline_from_ios_randomized.json"), user);

        assertTrue(result.containsKey("success"));
        assertTrue((Boolean) result.get("success"));

        // Create a spy to retrieve all LocationDataEvents pushed into RabbitMQ
        ArgumentCaptor<LocationDataEvent> eventCaptor = ArgumentCaptor.forClass(LocationDataEvent.class);
        verify(mock, times(118)).convertAndSend(eq(RabbitMQConfig.EXCHANGE_NAME), eq(RabbitMQConfig.LOCATION_DATA_ROUTING_KEY), eventCaptor.capture());

        List<LocationDataEvent> capturedEvents = eventCaptor.getAllValues();
        assertEquals(118, capturedEvents.size());

        // Verify that all events are for the correct user
        for (LocationDataEvent event : capturedEvents) {
            assertEquals("test", event.getUsername());
            assertNotNull(event.getPoints());
            assertFalse(event.getPoints().isEmpty());

            event.getPoints().forEach(point -> assertNotNull(point.getAccuracyMeters()));
        }

    }
}