package com.qaup.collision.common.adapter;

import com.qaup.system.domain.SysVehicleInfo;
import com.qaup.system.domain.SysVehicleType;
import com.qaup.system.service.ISysDriverInfoService;
import com.qaup.system.service.ISysVehicleInfoService;
import com.qaup.system.service.ISysVehicleTypeService;
import com.qaup.collision.common.model.spatial.VehicleLocation;
import com.qaup.collision.common.model.MovingObject;
import com.qaup.collision.common.model.MovingObject.MovingObjectType;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.quality.Strictness;
import org.mockito.junit.jupiter.MockitoSettings;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

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

/**
 * QuapDataAdapter单元测试
 * 验证适配器的数据访问功能
 */
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class QuapDataAdapterTest {

    @Mock
    private ISysVehicleInfoService vehicleInfoService;

    @Mock
    private ISysDriverInfoService driverInfoService;

    @Mock
    private ISysVehicleTypeService vehicleTypeService;

    @InjectMocks
    private QuapDataAdapter quapDataAdapter;

    private GeometryFactory geometryFactory;
    private SysVehicleInfo testVehicleInfo;

    @BeforeEach
    void setUp() {
        geometryFactory = new GeometryFactory();
        
        // 创建测试用的车辆信息
        testVehicleInfo = new SysVehicleInfo();
        testVehicleInfo.setVehicleId(1L);
        testVehicleInfo.setLicensePlate("测A12345");
        testVehicleInfo.setTypeCode("NM"); // 普通车辆类型编码
        testVehicleInfo.setOwningUnit("测试单位");

        // 模拟车辆类型服务，支持新的类型编码系统
        SysVehicleType normalVehicleType = new SysVehicleType();
        normalVehicleType.setTypeId(1L);
        normalVehicleType.setTypeCode("NM");
        normalVehicleType.setTypeName("普通车辆");
        when(vehicleTypeService.selectSysVehicleTypeByCode("NM")).thenReturn(normalVehicleType);
        when(vehicleTypeService.selectSysVehicleTypeById(1L)).thenReturn(normalVehicleType);

        SysVehicleType unmannedVehicleType = new SysVehicleType();
        unmannedVehicleType.setTypeId(2L);
        unmannedVehicleType.setTypeCode("UV");
        unmannedVehicleType.setTypeName("无人车");
        when(vehicleTypeService.selectSysVehicleTypeByCode("UV")).thenReturn(unmannedVehicleType);
        when(vehicleTypeService.selectSysVehicleTypeById(2L)).thenReturn(unmannedVehicleType);

        SysVehicleType specialVehicleType = new SysVehicleType();
        specialVehicleType.setTypeId(3L);
        specialVehicleType.setTypeCode("SP");
        specialVehicleType.setTypeName("特勤车辆");
        when(vehicleTypeService.selectSysVehicleTypeByCode("SP")).thenReturn(specialVehicleType);
        when(vehicleTypeService.selectSysVehicleTypeById(3L)).thenReturn(specialVehicleType);

        // 对于未找到的类型，返回null
        when(vehicleTypeService.selectSysVehicleTypeByCode("UNKNOWN")).thenReturn(null);
        when(vehicleTypeService.selectSysVehicleTypeById(999L)).thenReturn(null);
    }

    @Test
    void testFindVehicleById_Success() {
        // 准备测试数据
        Long vehicleId = 1L;
        when(vehicleInfoService.selectSysVehicleInfoByVehicleId(vehicleId))
                .thenReturn(testVehicleInfo);

        // 执行测试
        Optional<SysVehicleInfo> result = quapDataAdapter.findVehicleById(vehicleId);

        // 验证结果
        assertTrue(result.isPresent());
        assertEquals(testVehicleInfo.getVehicleId(), result.get().getVehicleId());
        assertEquals(testVehicleInfo.getLicensePlate(), result.get().getLicensePlate());
        
        // 验证方法调用
        verify(vehicleInfoService).selectSysVehicleInfoByVehicleId(vehicleId);
    }

    @Test
    void testFindVehicleById_NotFound() {
        // 准备测试数据
        Long vehicleId = 999L;
        when(vehicleInfoService.selectSysVehicleInfoByVehicleId(vehicleId))
                .thenReturn(null);

        // 执行测试
        Optional<SysVehicleInfo> result = quapDataAdapter.findVehicleById(vehicleId);

        // 验证结果
        assertFalse(result.isPresent());
        
        // 验证方法调用
        verify(vehicleInfoService).selectSysVehicleInfoByVehicleId(vehicleId);
    }

    @Test
    void testFindVehicleByLicensePlate_Success() {
        // 准备测试数据
        String licensePlate = "测A12345";
        List<SysVehicleInfo> vehicleList = Arrays.asList(testVehicleInfo);
        
        when(vehicleInfoService.selectSysVehicleInfoList(any(SysVehicleInfo.class)))
                .thenReturn(vehicleList);

        // 执行测试
        Optional<SysVehicleInfo> result = quapDataAdapter.findVehicleByLicensePlate(licensePlate);

        // 验证结果
        assertTrue(result.isPresent());
        assertEquals(licensePlate, result.get().getLicensePlate());
        
        // 验证方法调用
        verify(vehicleInfoService).selectSysVehicleInfoList(any(SysVehicleInfo.class));
    }

    @Test
    void testFindVehicleByLicensePlate_NotFound() {
        // 准备测试数据
        String licensePlate = "不存在车牌";
        when(vehicleInfoService.selectSysVehicleInfoList(any(SysVehicleInfo.class)))
                .thenReturn(Arrays.asList());

        // 执行测试
        Optional<SysVehicleInfo> result = quapDataAdapter.findVehicleByLicensePlate(licensePlate);

        // 验证结果
        assertFalse(result.isPresent());
    }

    @Test
    void testFindVehiclesByTypeCode() {
        // 准备测试数据
        String typeCode = "NM";
        List<SysVehicleInfo> expectedVehicles = Arrays.asList(testVehicleInfo);
        
        when(vehicleInfoService.selectSysVehicleInfoList(any(SysVehicleInfo.class)))
                .thenReturn(expectedVehicles);

        // 执行测试
        List<SysVehicleInfo> result = quapDataAdapter.findVehiclesByTypeCode(typeCode);

        // 验证结果
        assertEquals(1, result.size());
        assertEquals(testVehicleInfo.getVehicleId(), result.get(0).getVehicleId());
        
        // 验证方法调用
        verify(vehicleInfoService).selectSysVehicleInfoList(any(SysVehicleInfo.class));
    }

    @Test
    void testFindVehiclesByType_Deprecated() {
        // 准备测试数据
        Long typeId = 1L;
        List<SysVehicleInfo> expectedVehicles = Arrays.asList(testVehicleInfo);
        
        when(vehicleInfoService.selectSysVehicleInfoList(any(SysVehicleInfo.class)))
                .thenReturn(expectedVehicles);

        // 执行测试
        List<SysVehicleInfo> result = quapDataAdapter.findVehiclesByType(typeId);

        // 验证结果
        assertEquals(1, result.size());
        assertEquals(testVehicleInfo.getVehicleId(), result.get(0).getVehicleId());
        
        // 验证方法调用
        verify(vehicleTypeService).selectSysVehicleTypeById(typeId);
        verify(vehicleInfoService).selectSysVehicleInfoList(any(SysVehicleInfo.class));
    }

    @Test
    void testFindAllVehicles() {
        // 准备测试数据
        List<SysVehicleInfo> expectedVehicles = Arrays.asList(testVehicleInfo);
        
        when(vehicleInfoService.selectSysVehicleInfoList(any(SysVehicleInfo.class)))
                .thenReturn(expectedVehicles);

        // 执行测试
        List<SysVehicleInfo> result = quapDataAdapter.findAllVehicles();

        // 验证结果
        assertEquals(1, result.size());
        assertEquals(testVehicleInfo, result.get(0));
    }

    @Test
    void testSaveVehicle_Insert() {
        // 准备测试数据 - 新车辆（ID为null）
        SysVehicleInfo newVehicle = new SysVehicleInfo();
        newVehicle.setLicensePlate("测B67890");
        newVehicle.setTypeCode("UV");
        
        when(vehicleInfoService.insertSysVehicleInfo(newVehicle))
                .thenReturn(1);

        // 执行测试
        boolean result = quapDataAdapter.saveVehicle(newVehicle);

        // 验证结果
        assertTrue(result);
        
        // 验证方法调用
        verify(vehicleInfoService).insertSysVehicleInfo(newVehicle);
        verify(vehicleInfoService, never()).updateSysVehicleInfo(any());
    }

    @Test
    void testSaveVehicle_Update() {
        // 准备测试数据 - 现有车辆（ID不为null）
        testVehicleInfo.setVehicleId(1L);
        
        when(vehicleInfoService.updateSysVehicleInfo(testVehicleInfo))
                .thenReturn(1);

        // 执行测试
        boolean result = quapDataAdapter.saveVehicle(testVehicleInfo);

        // 验证结果
        assertTrue(result);
        
        // 验证方法调用
        verify(vehicleInfoService).updateSysVehicleInfo(testVehicleInfo);
        verify(vehicleInfoService, never()).insertSysVehicleInfo(any());
    }

    @Test
    void testConvertToVehicleLocation() {
        // 准备测试数据
        Point location = geometryFactory.createPoint(new Coordinate(120.0, 36.0));
        LocalDateTime timestamp = LocalDateTime.now();

        // 执行测试
        VehicleLocation result = quapDataAdapter.convertToVehicleLocation(
                testVehicleInfo, location, timestamp);

        // 验证结果
        assertNotNull(result);
        assertEquals(testVehicleInfo.getVehicleId(), result.getVehicleId());
        assertEquals(location, result.getLocation());
        assertEquals(timestamp, result.getTimestamp());
    }

    @Test
    void testConvertToVehicleLocation_NullInput() {
        // 执行测试
        VehicleLocation result = quapDataAdapter.convertToVehicleLocation(
                null, null, null);

        // 验证结果
        assertNull(result);
    }


    @Test
    void testBuildVehicleQueryCondition() {
        // 执行测试
        SysVehicleInfo condition = quapDataAdapter.buildVehicleQueryCondition(
                "测A12345", "NM", "测试单位");

        // 验证结果
        assertNotNull(condition);
        assertEquals("测A12345", condition.getLicensePlate());
        assertEquals("NM", condition.getTypeCode());
        assertEquals("测试单位", condition.getOwningUnit());
    }

    @Test
    void testFindVehiclesByIds() {
        // 准备测试数据
        List<Long> vehicleIds = Arrays.asList(1L, 2L);

        when(vehicleInfoService.selectSysVehicleInfoByVehicleId(1L))
                .thenReturn(testVehicleInfo);
        when(vehicleInfoService.selectSysVehicleInfoByVehicleId(2L))
                .thenReturn(null);

        // 执行测试
        List<SysVehicleInfo> result = quapDataAdapter.findVehiclesByIds(vehicleIds);

        // 验证结果
        assertEquals(1, result.size());
        assertEquals(testVehicleInfo, result.get(0));
    }

    @Test
    void testFindVehiclesByIds_EmptyList() {
        // 执行测试
        List<SysVehicleInfo> result = quapDataAdapter.findVehiclesByIds(Arrays.asList());

        // 验证结果
        assertTrue(result.isEmpty());
    }

    @Test
    void testIsInitialized() {
        // 执行测试
        boolean result = quapDataAdapter.isInitialized();

        // 验证结果
        assertTrue(result); // 所有Service都通过@Mock注入，不为null
    }
}
