package com.ruoyi.info.collection.controller;

import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.vo.BaseStaffImportSubmitResultVO;
import com.ruoyi.info.collection.service.ICcdiBaseStaffAssetImportService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffImportService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffService;
import com.ruoyi.info.collection.utils.EasyExcelUtil;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.mock.web.MockMultipartFile;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class CcdiBaseStaffControllerTest {

    @InjectMocks
    private CcdiBaseStaffController controller;

    @Mock
    private ICcdiBaseStaffService baseStaffService;

    @Mock
    private ICcdiBaseStaffImportService importAsyncService;

    @Mock
    private ICcdiBaseStaffAssetImportService baseStaffAssetImportService;

    @Test
    void importTemplate_shouldDownloadDualSheetTemplate() {
        try (MockedStatic<EasyExcelUtil> mocked = mockStatic(EasyExcelUtil.class)) {
            controller.importTemplate(null);

            mocked.verify(() -> EasyExcelUtil.importTemplateWithDictDropdown(
                    null,
                    CcdiBaseStaffExcel.class,
                    "员工信息",
                    CcdiBaseStaffAssetInfoExcel.class,
                    "员工资产信息",
                    "员工信息维护导入模板"
            ));
        }
    }

    @Test
    void importData_shouldWarnWhenBothSheetsAreEmpty() throws Exception {
        MockMultipartFile file = new MockMultipartFile(
                "file",
                "base-staff-empty.xlsx",
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                "empty".getBytes(StandardCharsets.UTF_8)
        );

        try (MockedStatic<EasyExcelUtil> mocked = mockStatic(EasyExcelUtil.class)) {
            mocked.when(() -> EasyExcelUtil.importExcel(any(InputStream.class), eq(CcdiBaseStaffExcel.class), eq("员工信息")))
                    .thenReturn(List.of());
            mocked.when(() -> EasyExcelUtil.importExcel(any(InputStream.class), eq(CcdiBaseStaffAssetInfoExcel.class), eq("员工资产信息")))
                    .thenReturn(List.of());

            AjaxResult result = controller.importData(file);

            assertEquals(HttpStatus.ERROR, result.get(AjaxResult.CODE_TAG));
            assertEquals("至少需要一条数据", result.get(AjaxResult.MSG_TAG));
            verifyNoInteractions(baseStaffService);
        }
    }

    @Test
    void importData_shouldSubmitOnlyStaffTaskWhenOnlyStaffSheetHasRows() throws Exception {
        MockMultipartFile file = new MockMultipartFile(
                "file",
                "base-staff.xlsx",
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                "staff".getBytes(StandardCharsets.UTF_8)
        );
        CcdiBaseStaffExcel staffExcel = new CcdiBaseStaffExcel();
        staffExcel.setStaffId(1001L);
        BaseStaffImportSubmitResultVO submitResult = new BaseStaffImportSubmitResultVO();
        submitResult.setStaffTaskId("staff-task-1");
        when(baseStaffService.importBaseStaffWithAssets(List.of(staffExcel), List.of())).thenReturn(submitResult);

        try (MockedStatic<EasyExcelUtil> mocked = mockStatic(EasyExcelUtil.class)) {
            mocked.when(() -> EasyExcelUtil.importExcel(any(InputStream.class), eq(CcdiBaseStaffExcel.class), eq("员工信息")))
                    .thenReturn(List.of(staffExcel));
            mocked.when(() -> EasyExcelUtil.importExcel(any(InputStream.class), eq(CcdiBaseStaffAssetInfoExcel.class), eq("员工资产信息")))
                    .thenReturn(List.of());

            AjaxResult result = controller.importData(file);

            assertEquals(HttpStatus.SUCCESS, result.get(AjaxResult.CODE_TAG));
            assertEquals("导入任务已提交,正在后台处理", result.get(AjaxResult.MSG_TAG));
            Object data = result.get(AjaxResult.DATA_TAG);
            assertEquals("staff-task-1", data.getClass().getMethod("getStaffTaskId").invoke(data));
            assertNull(data.getClass().getMethod("getAssetTaskId").invoke(data));
        }
    }

    @Test
    void importData_shouldSubmitTwoTasksWhenBothSheetsHaveRows() throws Exception {
        MockMultipartFile file = new MockMultipartFile(
                "file",
                "base-staff-both.xlsx",
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                "both".getBytes(StandardCharsets.UTF_8)
        );
        CcdiBaseStaffExcel staffExcel = new CcdiBaseStaffExcel();
        staffExcel.setStaffId(1002L);
        CcdiBaseStaffAssetInfoExcel assetExcel = new CcdiBaseStaffAssetInfoExcel();
        assetExcel.setPersonId("320101199001010011");
        BaseStaffImportSubmitResultVO submitResult = new BaseStaffImportSubmitResultVO();
        submitResult.setStaffTaskId("staff-task-2");
        submitResult.setAssetTaskId("asset-task-2");
        when(baseStaffService.importBaseStaffWithAssets(List.of(staffExcel), List.of(assetExcel))).thenReturn(submitResult);

        try (MockedStatic<EasyExcelUtil> mocked = mockStatic(EasyExcelUtil.class)) {
            mocked.when(() -> EasyExcelUtil.importExcel(any(InputStream.class), eq(CcdiBaseStaffExcel.class), eq("员工信息")))
                    .thenReturn(List.of(staffExcel));
            mocked.when(() -> EasyExcelUtil.importExcel(any(InputStream.class), eq(CcdiBaseStaffAssetInfoExcel.class), eq("员工资产信息")))
                    .thenReturn(List.of(assetExcel));

            AjaxResult result = controller.importData(file);

            assertEquals(HttpStatus.SUCCESS, result.get(AjaxResult.CODE_TAG));
            Object data = result.get(AjaxResult.DATA_TAG);
            assertEquals("staff-task-2", data.getClass().getMethod("getStaffTaskId").invoke(data));
            assertEquals("asset-task-2", data.getClass().getMethod("getAssetTaskId").invoke(data));
        }
    }
}
