package com.qaup.collision.pathconflict.service;

import com.qaup.collision.common.model.MovingObject;
import com.qaup.collision.common.model.MovingObject.MovingObjectType;
import com.qaup.collision.pathconflict.repository.ObjectRouteAssignmentRepository;
import com.qaup.collision.pathconflict.repository.TransportRouteRepository;
import com.qaup.collision.pathconflict.repository.ConflictAlertLogRepository;
import com.qaup.collision.pathconflict.model.entity.ObjectRouteAssignment;
import com.qaup.collision.pathconflict.model.entity.TransportRoute;
import com.qaup.collision.dataprocessing.service.CoordinateSystemService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationEventPublisher;

import java.util.Arrays;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

/**
 * 测试PathConflictDetectionService处理null速度的情况
 */
@ExtendWith(MockitoExtension.class)
class PathConflictDetectionServiceNullSpeedTest {

    @Mock
    private ObjectRouteAssignmentRepository objectRouteAssignmentRepository;

    @Mock
    private TransportRouteRepository routeRepository;

    @Mock
    private ConflictAlertLogRepository conflictAlertLogRepository;

    @Mock
    private ApplicationEventPublisher eventPublisher;

    @Mock
    private CoordinateSystemService coordinateSystemService;

    @InjectMocks
    private PathConflictDetectionService pathConflictDetectionService;

    private GeometryFactory geometryFactory;

    @BeforeEach
    void setUp() {
        geometryFactory = new GeometryFactory();
    }

    @Test
    void testDetectPathConflicts_WithNullSpeed_ShouldNotThrowException() {
        // 创建两个MovingObject，其中一个速度为null
        Point position1 = geometryFactory.createPoint(new Coordinate(120.0, 36.0));
        Point position2 = geometryFactory.createPoint(new Coordinate(120.1, 36.1));

        MovingObject obj1 = MovingObject.builder()
                .objectId("UV001")
                .objectType(MovingObjectType.UNMANNED_VEHICLE)
                .objectName("测试无人车1")
                .currentPosition(position1)
                .currentSpeed(null) // 速度为null
                .currentHeading(90.0)
                .altitude(0.0)
                .build();

        MovingObject obj2 = MovingObject.builder()
                .objectId("UV002")
                .objectType(MovingObjectType.UNMANNED_VEHICLE)
                .objectName("测试无人车2")
                .currentPosition(position2)
                .currentSpeed(15.0) // 正常速度
                .currentHeading(180.0)
                .altitude(0.0)
                .build();

        // Mock路径分配和路径数据
        ObjectRouteAssignment assignment1 = new ObjectRouteAssignment();
        assignment1.setAssignedRouteId(1L);

        ObjectRouteAssignment assignment2 = new ObjectRouteAssignment();
        assignment2.setAssignedRouteId(2L);

        TransportRoute route1 = new TransportRoute();
        route1.setId(1L);
        route1.setRouteName("测试路径1");

        TransportRoute route2 = new TransportRoute();
        route2.setId(2L);
        route2.setRouteName("测试路径2");

        when(objectRouteAssignmentRepository.findFirstByObjectNameAndObjectTypeOrderByAssignedAtDesc(
                anyString(), any(ObjectRouteAssignment.ObjectType.class)))
                .thenReturn(Optional.of(assignment1))
                .thenReturn(Optional.of(assignment2));

        when(routeRepository.findById(1L)).thenReturn(Optional.of(route1));
        when(routeRepository.findById(2L)).thenReturn(Optional.of(route2));

        // 测试：调用detectPathConflicts不应该抛出NullPointerException
        assertDoesNotThrow(() -> {
            pathConflictDetectionService.detectPathConflicts(Arrays.asList(obj1, obj2));
        });
    }

    @Test
    void testDetectPathConflicts_WithBothNullSpeeds_ShouldNotThrowException() {
        // 创建两个MovingObject，速度都为null
        Point position1 = geometryFactory.createPoint(new Coordinate(120.0, 36.0));
        Point position2 = geometryFactory.createPoint(new Coordinate(120.1, 36.1));

        MovingObject obj1 = MovingObject.builder()
                .objectId("UV001")
                .objectType(MovingObjectType.UNMANNED_VEHICLE)
                .objectName("测试无人车1")
                .currentPosition(position1)
                .currentSpeed(null) // 速度为null
                .currentHeading(90.0)
                .altitude(0.0)
                .build();

        MovingObject obj2 = MovingObject.builder()
                .objectId("UV002")
                .objectType(MovingObjectType.UNMANNED_VEHICLE)
                .objectName("测试无人车2")
                .currentPosition(position2)
                .currentSpeed(null) // 速度也为null
                .currentHeading(180.0)
                .altitude(0.0)
                .build();

        // Mock路径分配和路径数据
        ObjectRouteAssignment assignment1 = new ObjectRouteAssignment();
        assignment1.setAssignedRouteId(1L);

        ObjectRouteAssignment assignment2 = new ObjectRouteAssignment();
        assignment2.setAssignedRouteId(2L);

        TransportRoute route1 = new TransportRoute();
        route1.setId(1L);
        route1.setRouteName("测试路径1");

        TransportRoute route2 = new TransportRoute();
        route2.setId(2L);
        route2.setRouteName("测试路径2");

        when(objectRouteAssignmentRepository.findFirstByObjectNameAndObjectTypeOrderByAssignedAtDesc(
                anyString(), any(ObjectRouteAssignment.ObjectType.class)))
                .thenReturn(Optional.of(assignment1))
                .thenReturn(Optional.of(assignment2));

        when(routeRepository.findById(1L)).thenReturn(Optional.of(route1));
        when(routeRepository.findById(2L)).thenReturn(Optional.of(route2));

        // 测试：调用detectPathConflicts不应该抛出NullPointerException
        assertDoesNotThrow(() -> {
            pathConflictDetectionService.detectPathConflicts(Arrays.asList(obj1, obj2));
        });
    }
}
