package com.njcn.rdms.module.project.service.product;

import com.njcn.rdms.framework.common.exception.ServiceException;
import com.njcn.rdms.framework.common.pojo.CommonResult;
import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.module.project.controller.admin.product.vo.activity.ProductActivityPageReqVO;
import com.njcn.rdms.module.project.controller.admin.product.vo.activity.ProductActivityRespVO;
import com.njcn.rdms.module.project.controller.admin.product.vo.activity.ProductActivityTimelinePageReqVO;
import com.njcn.rdms.module.project.controller.admin.product.vo.activity.ProductActivityTimelineRespVO;
import com.njcn.rdms.framework.test.core.ut.BaseMockitoUnitTest;
import com.njcn.rdms.module.project.controller.admin.product.vo.setting.ProductSettingLifecycleRespVO;
import com.njcn.rdms.module.project.controller.admin.product.vo.setting.ProductSettingRespVO;
import com.njcn.rdms.module.project.dal.dataobject.product.ProductDO;
import com.njcn.rdms.module.project.dal.mysql.product.ProductMapper;
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
import com.njcn.rdms.module.system.api.user.AdminUserApi;
import com.njcn.rdms.module.system.api.user.dto.AdminUserRespDTO;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

class ProductSettingServiceImplTest extends BaseMockitoUnitTest {

    @InjectMocks
    private ProductSettingServiceImpl productSettingService;
    @Mock
    private AdminUserApi adminUserApi;
    @Mock
    private ProductMapper productMapper;
    @Mock
    private ProductStatusViewService productStatusViewService;
    @Mock
    private ProductActivityQueryService productActivityQueryService;
    @Mock
    private ProductActivityTimelineQueryService productActivityTimelineQueryService;

    @Test
    void getProductSettings_shouldAssembleBaseInfoAndLifecycleActions() {
        Long productId = 1001L;
        Long managerUserId = 2002L;
        ProductDO product = new ProductDO();
        product.setId(productId);
        product.setCode("CNPD2026001");
        product.setDirectionCode("direction_value");
        product.setName("统一交付平台");
        product.setManagerUserId(managerUserId);
        product.setDescription("产品描述");
        product.setStatusCode("active");
        product.setLastStatusReason("恢复正常推进");

        AdminUserRespDTO manager = new AdminUserRespDTO();
        manager.setId(managerUserId);
        manager.setNickname("张三");

        ProductSettingLifecycleRespVO lifecycle = new ProductSettingLifecycleRespVO();
        lifecycle.setStatusCode("active");
        lifecycle.setStatusName("启用");
        lifecycle.setTerminal(false);
        lifecycle.setAllowEdit(true);
        lifecycle.setLastStatusReason("恢复正常推进");
        lifecycle.setAvailableActions(Collections.emptyList());

        when(productMapper.selectById(productId)).thenReturn(product);
        when(adminUserApi.getUser(managerUserId)).thenReturn(CommonResult.success(manager));
        when(productStatusViewService.getLifecycle("active", "恢复正常推进")).thenReturn(lifecycle);

        ProductSettingRespVO result = productSettingService.getProductSettings(productId);

        assertEquals("统一交付平台", result.getBaseInfo().getName());
        assertEquals("张三", result.getBaseInfo().getManagerUserNickname());
        assertEquals("启用", result.getLifecycle().getStatusName());
        assertEquals(false, result.getLifecycle().getTerminal());
        assertEquals(true, result.getLifecycle().getAllowEdit());
    }

    @Test
    void getProductSettings_shouldReturnNullManagerNicknameWhenManagerUserIdIsNull() {
        Long productId = 1002L;
        ProductDO product = new ProductDO();
        product.setId(productId);
        product.setCode("CNPD2026002");
        product.setDirectionCode("direction_value");
        product.setName("产品A");
        product.setManagerUserId(null);
        product.setStatusCode("active");
        ProductSettingLifecycleRespVO lifecycle = new ProductSettingLifecycleRespVO();
        lifecycle.setStatusCode("active");
        lifecycle.setAvailableActions(Collections.emptyList());

        when(productMapper.selectById(productId)).thenReturn(product);
        when(productStatusViewService.getLifecycle("active", null)).thenReturn(lifecycle);

        ProductSettingRespVO result = productSettingService.getProductSettings(productId);

        assertNull(result.getBaseInfo().getManagerUserNickname());
        verifyNoInteractions(adminUserApi);
    }

    @Test
    void getProductSettings_shouldReturnEmptyActionsWhenNoStatusTransitions() {
        Long productId = 1003L;
        Long managerUserId = 2003L;
        ProductDO product = new ProductDO();
        product.setId(productId);
        product.setCode("CNPD2026003");
        product.setDirectionCode("direction_value");
        product.setName("产品B");
        product.setManagerUserId(managerUserId);
        product.setStatusCode("paused");

        AdminUserRespDTO manager = new AdminUserRespDTO();
        manager.setId(managerUserId);
        manager.setNickname("李四");
        ProductSettingLifecycleRespVO lifecycle = new ProductSettingLifecycleRespVO();
        lifecycle.setStatusCode("paused");
        lifecycle.setAvailableActions(Collections.emptyList());

        when(productMapper.selectById(productId)).thenReturn(product);
        when(adminUserApi.getUser(managerUserId)).thenReturn(CommonResult.success(manager));
        when(productStatusViewService.getLifecycle("paused", null)).thenReturn(lifecycle);

        ProductSettingRespVO result = productSettingService.getProductSettings(productId);

        assertNotNull(result.getLifecycle().getAvailableActions());
        assertTrue(result.getLifecycle().getAvailableActions().isEmpty());
    }

    @Test
    void getProductActivities_shouldValidateProductAndDelegate() {
        Long productId = 1004L;
        ProductDO product = new ProductDO();
        product.setId(productId);

        ProductActivityPageReqVO reqVO = new ProductActivityPageReqVO();
        reqVO.setPageNo(1);
        reqVO.setPageSize(10);

        ProductActivityRespVO respVO = new ProductActivityRespVO();
        respVO.setType("status");
        PageResult<ProductActivityRespVO> pageResult = new PageResult<>(List.of(respVO), 1L);

        when(productMapper.selectById(productId)).thenReturn(product);
        when(productActivityQueryService.getProductActivities(productId, reqVO)).thenReturn(pageResult);

        PageResult<ProductActivityRespVO> result = productSettingService.getProductActivities(productId, reqVO);

        assertEquals(1L, result.getTotal());
        assertEquals("status", result.getList().get(0).getType());
    }

    @Test
    void getProductActivities_whenProductMissing_shouldThrowException() {
        Long productId = 1005L;
        ProductActivityPageReqVO reqVO = new ProductActivityPageReqVO();
        reqVO.setPageNo(1);
        reqVO.setPageSize(10);

        when(productMapper.selectById(productId)).thenReturn(null);

        ServiceException ex = assertThrows(ServiceException.class,
                () -> productSettingService.getProductActivities(productId, reqVO));
        assertEquals(ErrorCodeConstants.PRODUCT_NOT_EXISTS.getCode(), ex.getCode());
    }

    @Test
    void getProductActivityTimelinePage_shouldValidateProductAndDelegate() {
        Long productId = 1006L;
        ProductDO product = new ProductDO();
        product.setId(productId);

        ProductActivityTimelinePageReqVO reqVO = new ProductActivityTimelinePageReqVO();
        reqVO.setPageNo(1);
        reqVO.setPageSize(10);

        ProductActivityTimelineRespVO respVO = new ProductActivityTimelineRespVO();
        respVO.setId("status:11");
        PageResult<ProductActivityTimelineRespVO> pageResult = new PageResult<>(List.of(respVO), 1L);

        when(productMapper.selectById(productId)).thenReturn(product);
        when(productActivityTimelineQueryService.getProductActivityTimelinePage(productId, reqVO))
                .thenReturn(pageResult);

        PageResult<ProductActivityTimelineRespVO> result =
                productSettingService.getProductActivityTimelinePage(productId, reqVO);

        assertEquals(1L, result.getTotal());
        assertEquals("status:11", result.getList().get(0).getId());
    }

    @Test
    void getProductActivityTimelinePage_whenProductMissing_shouldThrowException() {
        Long productId = 1007L;
        ProductActivityTimelinePageReqVO reqVO = new ProductActivityTimelinePageReqVO();
        reqVO.setPageNo(1);
        reqVO.setPageSize(10);

        when(productMapper.selectById(productId)).thenReturn(null);

        ServiceException ex = assertThrows(ServiceException.class,
                () -> productSettingService.getProductActivityTimelinePage(productId, reqVO));
        assertEquals(ErrorCodeConstants.PRODUCT_NOT_EXISTS.getCode(), ex.getCode());
    }

}
