package com.clx.performance.service.impl;

import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.dto.gd.GdRouteDTO;
import com.clx.performance.enums.PerformanceResultEnum;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.param.app.OrderChildLoadRangeCheckParam;
import com.clx.performance.service.OrderChildOperateLimitConfigService;
import com.clx.performance.utils.gd.GdService;
import com.clx.performance.vo.app.OrderChildLoadRangeCheckResultVO;
import com.clx.performance.vo.pc.OrderChildOperateLimitConfigVO;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import java.math.BigDecimal;
import java.util.Arrays;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class OrderChildServiceImplTest {

    @InjectMocks
    private OrderChildServiceImpl orderChildService;

    @Mock
    private OrderChildOperateLimitConfigService orderChildOperateLimitConfigService;

    @Mock
    private GdService gdService;

    @Mock
    private OrderGoodsDao orderGoodsDao;
    @Mock
    private OrderChildDao orderChildDao;

    private OrderChildLoadRangeCheckParam param;
    private OrderChildOperateLimitConfigVO config;

    @Before
    public void setUp() {
        param = new OrderChildLoadRangeCheckParam();
        param.setLatitude(new BigDecimal("32.2304"));
        param.setLongitude(new BigDecimal("122.4737"));

        OrderChild orderChild = new OrderChild();
        orderChild.setOrderGoodsNo("123456789");
        orderChild.setTruckNo("黑A88888");
        Mockito.<com.msl.common.base.Optional<OrderChild>>when(orderChildDao.getByChildNo(param.getChildNo())).thenReturn(com.msl.common.base.Optional.of(orderChild));


        // 预设的返回值，根据具体业务逻辑可能需要调整
        OrderGoods orderGoods = new OrderGoods();
        orderGoods.setSendLatitude(BigDecimal.valueOf(31.2304));
        orderGoods.setSendLongitude(BigDecimal.valueOf(121.4737));
        Mockito.<com.msl.common.base.Optional<OrderGoods>>when(orderGoodsDao.getByOrderGoodsNo(orderChild.getOrderGoodsNo())).thenReturn(com.msl.common.base.Optional.of(orderGoods));

        // Mock配置
        config = new OrderChildOperateLimitConfigVO();
        config.setAllowUploadDistance(BigDecimal.valueOf(2));
        config.setStatus(1);
        when(orderChildOperateLimitConfigService.listConfig()).thenReturn(config);
    }

    @Test
    public void testLoadRangeCheckSuccess() {
        GdRouteDTO gdRoute = new GdRouteDTO();
        gdRoute.setDistance(1000);
        // 假设高德服务返回了一个有效的路线
        Mockito.when(gdService.getRoute(any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class))).thenReturn(Arrays.asList(gdRoute));

        OrderChildLoadRangeCheckResultVO result = orderChildService.loadRangeCheck(param);

        assertEquals(0, result.getCode().intValue());
        assertEquals("验证通过", result.getMsg());
    }

    @Test
    public void testLoadRangeCheckFailDueToConfigNull() {
        // 假设没有配置
        when(orderChildOperateLimitConfigService.listConfig()).thenReturn(null);

        OrderChildLoadRangeCheckResultVO result = orderChildService.loadRangeCheck(param);

        assertEquals(PerformanceResultEnum.ORDER_CHILD_LOAD_LIMIT_CONFIG_ERROR.getCode(), result.getCode().intValue());
        assertEquals(PerformanceResultEnum.ORDER_CHILD_LOAD_LIMIT_CONFIG_ERROR.getMsg(), result.getMsg());
    }

    @Test
    public void testLoadRangeCheckFailDueToDisabledConfig() {
        // 假设配置被禁用
        OrderChildOperateLimitConfigVO config = new OrderChildOperateLimitConfigVO();
        config.setStatus(0);
        config.setAllowUploadDistance(new BigDecimal("2"));
        when(orderChildOperateLimitConfigService.listConfig()).thenReturn(config);

        OrderChildLoadRangeCheckResultVO result = orderChildService.loadRangeCheck(param);

        assertEquals(0, result.getNeedAlert().intValue());
        assertEquals(PerformanceResultEnum.ORDER_CHILD_LOAD_LIMIT_CONFIG_DISABLED.getCode(), result.getCode().intValue());
        assertEquals(PerformanceResultEnum.ORDER_CHILD_LOAD_LIMIT_CONFIG_DISABLED.getMsg(), result.getMsg());
    }

    @Test
    public void testLoadRangeCheckFailDueToTruckLocation() {
        param.setLatitude(null);
        param.setLongitude(null);
        OrderChildLoadRangeCheckResultVO result = orderChildService.loadRangeCheck(param);
        assertEquals(PerformanceResultEnum.TRUCK_LOCATION_ERROR.getCode(), result.getCode().intValue());
        assertEquals(String.format(PerformanceResultEnum.TRUCK_LOCATION_ERROR.getMsg(), config.getAllowUploadDistance()), result.getMsg());
    }

    @Test
    public void testLoadRangeCheckFailDueToDistanceOut() {
        GdRouteDTO gdRoute = new GdRouteDTO();
        gdRoute.setDistance(5000);
        Mockito.when(gdService.getRoute(any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class))).thenReturn(Arrays.asList(gdRoute));

        OrderChildLoadRangeCheckResultVO result = orderChildService.loadRangeCheck(param);

        assertEquals(PerformanceResultEnum.TRUCK_LOCATION_OUT_OF_SEND_RANGE.getCode(), result.getCode().intValue());
        assertEquals(String.format(PerformanceResultEnum.TRUCK_LOCATION_OUT_OF_SEND_RANGE.getMsg(), config.getAllowUploadDistance()), result.getMsg());
    }
}
