package com.ruoyi.web.modules.booking.service.impl;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.DisplayName;
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 com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.booking.domain.AppMyAppointmentQuery;
import com.ruoyi.web.modules.booking.domain.AppMyAppointmentReviewBody;
import com.ruoyi.web.modules.booking.mapper.AppMyAppointmentMapper;
import com.ruoyi.web.modules.diagnosis.domain.BizServiceAppointment;
import com.ruoyi.web.modules.diagnosis.support.ServiceAppointmentRules;
import com.ruoyi.web.modules.farming.mapper.BizServiceAppointmentReviewMapper;

@ExtendWith(MockitoExtension.class)
@DisplayName("AppMyAppointmentServiceImpl")
class AppMyAppointmentServiceImplTest
{
    @Mock
    private AppMyAppointmentMapper appMyAppointmentMapper;

    @Mock
    private BizServiceAppointmentReviewMapper bizServiceAppointmentReviewMapper;

    @InjectMocks
    private AppMyAppointmentServiceImpl service;

    @Test
    @DisplayName("已完成不可取消")
    void cancelCompletedBlocked()
    {
        BizServiceAppointment row = ownedExpert(ServiceAppointmentRules.STATUS_COMPLETED);
        when(appMyAppointmentMapper.selectMyAppointmentByIdAndUser(1L, "u1")).thenReturn(row);
        assertThrows(ServiceException.class, () -> service.cancelAppointment(1L, "u1", "u1"));
    }

    @Test
    @DisplayName("待确认可取消")
    void cancelPending()
    {
        BizServiceAppointment row = ownedExpert(ServiceAppointmentRules.STATUS_PENDING);
        when(appMyAppointmentMapper.selectMyAppointmentByIdAndUser(1L, "u1")).thenReturn(row);
        when(appMyAppointmentMapper.cancelMyAppointment(1L, "u1", "u1")).thenReturn(1);
        assertEquals(1, service.cancelAppointment(1L, "u1", "u1"));
    }

    @Test
    @DisplayName("提交评价不更新 expert_rating")
    void submitReview()
    {
        BizServiceAppointment row = ownedExpert(ServiceAppointmentRules.STATUS_COMPLETED);
        when(appMyAppointmentMapper.selectMyAppointmentByIdAndUser(1L, "u1")).thenReturn(row);
        when(bizServiceAppointmentReviewMapper.countByAppointmentId(1L)).thenReturn(0);
        when(bizServiceAppointmentReviewMapper.insertBizServiceAppointmentReview(any())).thenAnswer(inv -> {
            com.ruoyi.web.modules.farming.domain.BizServiceAppointmentReview r = inv.getArgument(0);
            r.setId(99L);
            return 1;
        });

        AppMyAppointmentReviewBody body = new AppMyAppointmentReviewBody();
        body.setPunctualityScore(5);
        body.setAttitudeScore(5);
        body.setGuidanceScore(4);
        body.setSummary("服务很好");

        assertEquals(99L, service.submitAppointmentReview(1L, body, "u1", "扎西"));
        verify(bizServiceAppointmentReviewMapper, never()).selectExpertRatingScoreByProviderId(org.mockito.ArgumentMatchers.any());
    }

    @Test
    @DisplayName("列表需 createBy")
    void listRequiresUser()
    {
        assertThrows(ServiceException.class, () -> service.selectMyAppointmentList(new AppMyAppointmentQuery()));
    }

    private static BizServiceAppointment ownedExpert(int status)
    {
        BizServiceAppointment row = new BizServiceAppointment();
        row.setId(1L);
        row.setProviderType(ServiceAppointmentRules.PROVIDER_TYPE_EXPERT);
        row.setProviderId(10L);
        row.setStatus(status);
        row.setCreateBy("u1");
        return row;
    }
}
