package com.yimeng.okr.service;

import com.yimeng.okr.entity.PerformanceFeedback;
import com.yimeng.okr.exception.BusinessException;
import com.yimeng.okr.mapper.PerformanceFeedbackMapper;
import com.yimeng.okr.mapper.PerformanceScoreMapper;
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.springframework.context.ApplicationEventPublisher;

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

@ExtendWith(MockitoExtension.class)
class FeedbackServiceTest {

    @Mock PerformanceFeedbackMapper feedbackMapper;
    @Mock PerformanceScoreMapper scoreMapper;
    @Mock OkrService okrService;
    @Mock PerformanceService performanceService;
    @Mock AuthorizationService authorizationService;
    @Mock ApplicationEventPublisher publisher;
    @InjectMocks FeedbackService feedbackService;

    @Test
    void saveInterviewNotesSetsPendingEmployeeStatus() {
        when(feedbackMapper.selectOne(any())).thenReturn(null);

        PerformanceFeedback feedback = feedbackService.saveInterviewNotes(
                1L, 2L, 3L, "面谈记录", "亮点", "问题", "改进");

        assertEquals("PENDING_EMPLOYEE", feedback.getStatus());
        verify(authorizationService).requireCanManageUserData(3L, 2L);
        verify(feedbackMapper).insert(feedback);
    }

    @Test
    void submitEmployeeFeedbackSetsRepliedStatus() {
        PerformanceFeedback existing = feedback(1L, 2L, 3L);
        existing.setStatus("PENDING_EMPLOYEE");
        when(feedbackMapper.selectOne(any())).thenReturn(existing);

        PerformanceFeedback feedback = feedbackService.submitEmployeeFeedback(1L, 2L, "已沟通确认");

        assertEquals("已沟通确认", feedback.getEmployeeFeedback());
        assertEquals("REPLIED", feedback.getStatus());
        verify(feedbackMapper).updateById(existing);
    }

    @Test
    void submitEmployeeFeedbackRejectsBlankContent() {
        BusinessException ex = assertThrows(BusinessException.class,
                () -> feedbackService.submitEmployeeFeedback(1L, 2L, " "));

        assertTrue(ex.getMessage().contains("不能为空"));
        verify(feedbackMapper, never()).updateById(any());
    }

    @Test
    void submitEmployeeFeedbackRejectsClosedFeedback() {
        PerformanceFeedback existing = feedback(1L, 2L, 3L);
        existing.setStatus("CLOSED");
        existing.setEmployeeFeedback("已关闭反馈");
        when(feedbackMapper.selectOne(any())).thenReturn(existing);

        BusinessException ex = assertThrows(BusinessException.class,
                () -> feedbackService.submitEmployeeFeedback(1L, 2L, "再次补充"));

        assertTrue(ex.getMessage().contains("已关闭"));
        verify(feedbackMapper, never()).updateById(any());
    }

    @Test
    void closeFeedbackRequiresReplyAndMarksClosed() {
        PerformanceFeedback existing = feedback(1L, 2L, 3L);
        existing.setStatus("REPLIED");
        existing.setEmployeeFeedback("已沟通确认");
        when(feedbackMapper.selectOne(any())).thenReturn(existing);

        PerformanceFeedback closed = feedbackService.closeFeedback(1L, 2L, 3L);

        assertEquals("CLOSED", closed.getStatus());
        assertNotNull(closed.getClosedAt());
        verify(authorizationService).requireCanManageUserData(3L, 2L);
        verify(feedbackMapper).updateById(existing);
    }

    @Test
    void closeFeedbackRejectsMissingEmployeeReply() {
        PerformanceFeedback existing = feedback(1L, 2L, 3L);
        existing.setStatus("REPLIED");
        existing.setEmployeeFeedback("");
        when(feedbackMapper.selectOne(any())).thenReturn(existing);

        BusinessException ex = assertThrows(BusinessException.class,
                () -> feedbackService.closeFeedback(1L, 2L, 3L));

        assertTrue(ex.getMessage().contains("员工反馈"));
        verify(feedbackMapper, never()).updateById(any());
    }

    @Test
    void closeFeedbackRequiresRepliedStatus() {
        PerformanceFeedback existing = feedback(1L, 2L, 3L);
        existing.setStatus("PENDING_EMPLOYEE");
        existing.setEmployeeFeedback("手工补入反馈");
        when(feedbackMapper.selectOne(any())).thenReturn(existing);

        BusinessException ex = assertThrows(BusinessException.class,
                () -> feedbackService.closeFeedback(1L, 2L, 3L));

        assertTrue(ex.getMessage().contains("尚未回复"));
        verify(feedbackMapper, never()).updateById(any());
    }

    private PerformanceFeedback feedback(Long periodId, Long userId, Long superiorId) {
        PerformanceFeedback feedback = new PerformanceFeedback();
        feedback.setId(8L);
        feedback.setPeriodId(periodId);
        feedback.setUserId(userId);
        feedback.setSuperiorId(superiorId);
        return feedback;
    }
}
