package com.ruoyi.asset.controller;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.ruoyi.asset.domain.AmsRfidTag;
import com.ruoyi.asset.domain.RfidBindingContext;
import com.ruoyi.asset.service.IAmsAssetService;
import com.ruoyi.asset.service.IAmsRfidTagService;
import com.ruoyi.asset.service.IRfidBindingService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;

@ExtendWith(MockitoExtension.class)
class AmsRfidTagControllerTest
{
    @Mock
    private IAmsRfidTagService amsRfidTagService;

    @Mock
    private IAmsAssetService amsAssetService;

    @Mock
    private IRfidBindingService rfidBindingService;

    private TestAmsRfidTagController controller;

    @BeforeEach
    void setUp()
    {
        controller = new TestAmsRfidTagController();
        ReflectionTestUtils.setField(controller, "amsRfidTagService", amsRfidTagService);
        ReflectionTestUtils.setField(controller, "amsAssetService", amsAssetService);
        ReflectionTestUtils.setField(controller, "rfidBindingService", rfidBindingService);
    }

    /** Web绑定必须使用数据库中的标签EPC，并把当前登录人传给公共绑定服务 */
    @Test
    void bindSaveShouldDelegateToRfidBindingService()
    {
        AmsRfidTag tag = new AmsRfidTag();
        tag.setTagId(10L);
        tag.setEpcCode("EPC-001");
        when(amsRfidTagService.selectAmsRfidTagByTagId(10L)).thenReturn(tag);

        AjaxResult result = controller.bindSave(10L, "ASSET-001", "页面测试");

        ArgumentCaptor<RfidBindingContext> contextCaptor = ArgumentCaptor.forClass(RfidBindingContext.class);
        verify(rfidBindingService).bind(org.mockito.ArgumentMatchers.eq("ASSET-001"),
                org.mockito.ArgumentMatchers.eq("EPC-001"), contextCaptor.capture());
        assertEquals(1L, contextCaptor.getValue().getOperateUserId());
        assertEquals("管理员", contextCaptor.getValue().getOperateUserName());
        assertEquals("admin", contextCaptor.getValue().getOperateLoginName());
        assertEquals("页面测试", contextCaptor.getValue().getRemark());
        assertEquals(AjaxResult.Type.SUCCESS.value(), result.get(AjaxResult.CODE_TAG));
    }

    /** 标签不存在时不得调用公共绑定服务 */
    @Test
    void bindSaveShouldRejectMissingTag()
    {
        ServiceException exception = assertThrows(ServiceException.class,
                () -> controller.bindSave(10L, "ASSET-001", null));

        assertEquals("RFID标签不存在或已删除", exception.getMessage());
    }

    private static class TestAmsRfidTagController extends AmsRfidTagController
    {
        private final SysUser user;

        private TestAmsRfidTagController()
        {
            user = new SysUser();
            user.setUserId(1L);
            user.setUserName("管理员");
            user.setLoginName("admin");
        }

        @Override
        public SysUser getSysUser()
        {
            return user;
        }
    }
}
