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

import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.rdms.framework.test.core.ut.BaseMockitoUnitTest;
import com.njcn.rdms.module.project.controller.admin.project.project.vo.workbench.MyWorklogWeekRespVO;
import com.njcn.rdms.module.project.dal.dataobject.personal.PersonalItemDO;
import com.njcn.rdms.module.project.dal.dataobject.project.ProjectDO;
import com.njcn.rdms.module.project.dal.dataobject.project.task.ProjectTaskDO;
import com.njcn.rdms.module.project.dal.dataobject.project.task.TaskWorklogDO;
import com.njcn.rdms.module.project.dal.mysql.personal.PersonalItemMapper;
import com.njcn.rdms.module.project.dal.mysql.project.ProjectMapper;
import com.njcn.rdms.module.project.dal.mysql.project.task.ProjectTaskMapper;
import com.njcn.rdms.module.project.dal.mysql.project.task.TaskWorklogMapper;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

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

class MyWorklogServiceImplTest extends BaseMockitoUnitTest {

    private static final LocalDate MONDAY = LocalDate.of(2026, 6, 8);

    @InjectMocks
    private MyWorklogServiceImpl myWorklogService;
    @Mock
    private TaskWorklogMapper taskWorklogMapper;
    @Mock
    private ProjectTaskMapper projectTaskMapper;
    @Mock
    private PersonalItemMapper personalItemMapper;
    @Mock
    private ProjectMapper projectMapper;
    @Mock
    private MyTeamService myTeamService;

    private TaskWorklogDO worklog(Long taskId, LocalDate start, LocalDate end, String hours) {
        TaskWorklogDO w = new TaskWorklogDO();
        w.setTaskId(taskId);
        w.setUserId(100L);
        w.setStartDate(start);
        w.setEndDate(end);
        w.setDurationHours(new BigDecimal(hours));
        return w;
    }

    @Test
    void myWorklogWeek_dailyAndDistribution_kindResolution() {
        try (MockedStatic<SecurityFrameworkUtils> mock = mockStatic(SecurityFrameworkUtils.class)) {
            mock.when(SecurityFrameworkUtils::getLoginUserId).thenReturn(100L);
            // 任务1(项目10):周一~周三 12h → 每天 4h;事项2(个人事项):周三单天 3h
            when(taskWorklogMapper.selectListByUserIdAndPeriod(eq(100L), any(), any())).thenReturn(List.of(
                    worklog(1L, MONDAY, MONDAY.plusDays(2), "12"),
                    worklog(2L, MONDAY.plusDays(2), MONDAY.plusDays(2), "3")));
            ProjectTaskDO task = new ProjectTaskDO();
            task.setId(1L);
            task.setProjectId(10L);
            when(projectTaskMapper.selectBatchIds(anyCollection())).thenReturn(List.of(task));
            PersonalItemDO item = new PersonalItemDO();
            item.setId(2L);
            when(personalItemMapper.selectBatchIds(anyCollection())).thenReturn(List.of(item));
            ProjectDO project = new ProjectDO();
            project.setId(10L);
            project.setProjectName("收银台 V3");
            when(projectMapper.selectBatchIds(anyCollection())).thenReturn(List.of(project));

            MyWorklogWeekRespVO resp = myWorklogService.getMyWorklogWeek(MONDAY);
            assertEquals(MONDAY, resp.getWeekStart());
            assertEquals(5, resp.getDailyHours().size());
            assertEquals(0, new BigDecimal("4.00").compareTo(resp.getDailyHours().get(0))); // 周一
            assertEquals(0, new BigDecimal("7.00").compareTo(resp.getDailyHours().get(2))); // 周三 4+3
            assertEquals(0, new BigDecimal("0.00").compareTo(resp.getDailyHours().get(3))); // 周四
            assertEquals(2, resp.getDistribution().size());
            assertEquals("project", resp.getDistribution().get(0).getKind());
            assertEquals(0, new BigDecimal("12.00").compareTo(resp.getDistribution().get(0).getHours()));
            assertEquals("personal", resp.getDistribution().get(1).getKind());
            assertEquals(0, new BigDecimal("3.00").compareTo(resp.getDistribution().get(1).getHours()));
        }
    }

    @Test
    void teamWorklogWeek_memberWithoutWorklog_hasEmptyItems() {
        when(myTeamService.resolveTeamMembers()).thenReturn(List.of(
                new MyTeamService.TeamMember(100L, "我"),
                new MyTeamService.TeamMember(200L, "张三")));
        when(taskWorklogMapper.selectListByUserIdsAndPeriod(anyCollection(), any(), any()))
                .thenReturn(List.of());
        var resp = myWorklogService.getTeamWorklogWeek(MONDAY);
        assertEquals(2, resp.getMembers().size());
        assertEquals(100L, resp.getMembers().get(0).getUserId());
        assertEquals(0, resp.getMembers().get(0).getItems().size());
        assertEquals(0, resp.getMembers().get(1).getItems().size());
    }

}
