package com.ruoyi.web.modules.architecture.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.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
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.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.architecture.domain.BizEpidemicTreatmentStandard;
import com.ruoyi.web.modules.architecture.mapper.BizEpidemicTreatmentStandardMapper;
import com.ruoyi.web.modules.architecture.support.EpidemicTreatmentStandardTypeValidator;
import com.ruoyi.web.kb.support.KbApiProperties;
import com.ruoyi.web.kb.service.KnowledgeBaseClient;

@ExtendWith(MockitoExtension.class)
@DisplayName("BizEpidemicTreatmentStandardServiceImpl")
class BizEpidemicTreatmentStandardServiceImplTest
{

    @Mock
    private BizEpidemicTreatmentStandardMapper mapper;

    @Mock
    private KnowledgeBaseClient knowledgeBaseClient;

    @Mock
    private KbApiProperties kbApiProperties;

    @Mock
    private EpidemicTreatmentStandardTypeValidator epidemicTreatmentStandardTypeValidator;

    @InjectMocks
    private BizEpidemicTreatmentStandardServiceImpl service;

    @Test
    @DisplayName("修改已发布抛业务异常")
    void updatePublishedThrows()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(9L);
        db.setPublishStatus(1);
        db.setKbSyncStatus(1);
        when(mapper.selectBizEpidemicTreatmentStandardById(9L)).thenReturn(db);

        BizEpidemicTreatmentStandard incoming = baseRow();
        incoming.setId(9L);
        incoming.setStandardName("新名称一二");

        assertThrows(ServiceException.class, () -> service.updateBizEpidemicTreatmentStandard(incoming));
        verify(mapper, never()).updateBizEpidemicTreatmentStandard(any());
    }

    @Test
    @DisplayName("同步成功写 kb_doc_id（file_id）")
    void syncKbUpdatesState()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(3L);
        db.setPublishStatus(0);
        db.setKbSyncStatus(0);
        when(mapper.selectBizEpidemicTreatmentStandardById(3L)).thenReturn(db);
        when(kbApiProperties.getFileUrlBase()).thenReturn("");
        when(knowledgeBaseClient.uploadFileByUrl(eq("http://localhost/f"), eq("疫病诊疗标准"), eq("疫")))
                .thenReturn("KB-DOC-3");
        when(mapper.updateBizEpidemicTreatmentStandard(any())).thenReturn(1);

        assertEquals(1, service.syncKb(3L));

        verify(mapper).updateBizEpidemicTreatmentStandard(argThat(r ->
                r.getKbSyncStatus() == 1 && "KB-DOC-3".equals(r.getKbDocId())));
    }

    @Test
    @DisplayName("同步 Mapper 返回 0")
    void syncKbMapperReturnsZero()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(4L);
        db.setPublishStatus(0);
        db.setKbSyncStatus(0);
        when(mapper.selectBizEpidemicTreatmentStandardById(4L)).thenReturn(db);
        when(kbApiProperties.getFileUrlBase()).thenReturn("");
        when(knowledgeBaseClient.uploadFileByUrl(eq("http://localhost/f"), eq("疫病诊疗标准"), anyString()))
                .thenReturn("KB-DOC-4");
        when(mapper.updateBizEpidemicTreatmentStandard(any())).thenReturn(0);

        assertEquals(0, service.syncKb(4L));
        verify(mapper).updateBizEpidemicTreatmentStandard(any());
    }

    @Test
    @DisplayName("已同步禁止修改")
    void updateWhenSyncedRejected()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(10L);
        db.setPublishStatus(0);
        db.setKbSyncStatus(1);
        db.setKbDocId("LOCAL-10");
        when(mapper.selectBizEpidemicTreatmentStandardById(10L)).thenReturn(db);

        BizEpidemicTreatmentStandard incoming = baseRow();
        incoming.setId(10L);
        incoming.setIntroduction("改简介");
        assertThrows(ServiceException.class, () -> service.updateBizEpidemicTreatmentStandard(incoming));
        verify(mapper, never()).updateBizEpidemicTreatmentStandard(any());
    }

    @Test
    @DisplayName("下架成功：未发布+已同步，保留 kb_doc_id")
    void offline()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(20L);
        db.setPublishStatus(1);
        db.setKbSyncStatus(1);
        db.setKbDocId("REAL-KB-DOC");
        when(mapper.selectBizEpidemicTreatmentStandardById(20L)).thenReturn(db);
        when(mapper.updateBizEpidemicTreatmentStandard(any())).thenReturn(1);

        assertEquals(1, service.offline(20L));

        verify(mapper).updateBizEpidemicTreatmentStandard(argThat(r ->
                r.getPublishStatus() == 0
                        && r.getKbSyncStatus() == 1
                        && "REAL-KB-DOC".equals(r.getKbDocId())
                        && r.getOfflineTime() != null));
    }

    @Test
    @DisplayName("移出成功")
    void removeKb()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(13L);
        db.setPublishStatus(0);
        db.setKbSyncStatus(1);
        db.setKbDocId("DOC-13");
        when(mapper.selectBizEpidemicTreatmentStandardById(13L)).thenReturn(db);
        when(mapper.updateBizEpidemicTreatmentStandard(any())).thenReturn(1);

        assertEquals(1, service.removeKb(13L));
        verify(knowledgeBaseClient).deleteFile("DOC-13");
        verify(mapper).updateBizEpidemicTreatmentStandard(argThat(r ->
                r.getKbSyncStatus() == 0 && r.getKbDocId() == null));
    }

    @Test
    @DisplayName("发布成功")
    void publish()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(14L);
        db.setPublishStatus(0);
        db.setKbSyncStatus(1);
        when(mapper.selectBizEpidemicTreatmentStandardById(14L)).thenReturn(db);
        when(mapper.updateBizEpidemicTreatmentStandard(any())).thenReturn(1);

        assertEquals(1, service.publish(14L));
        verify(mapper).updateBizEpidemicTreatmentStandard(argThat(r ->
                r.getPublishStatus() == 1 && r.getPublishTime() != null));
    }

    @Test
    @DisplayName("未同步保存")
    void updateUnsynced()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(11L);
        db.setPublishStatus(0);
        db.setKbSyncStatus(0);
        db.setKbDocId(null);
        when(mapper.selectBizEpidemicTreatmentStandardById(11L)).thenReturn(db);
        when(mapper.updateBizEpidemicTreatmentStandard(any())).thenReturn(1);

        BizEpidemicTreatmentStandard incoming = baseRow();
        incoming.setId(11L);
        incoming.setIntroduction("仅本地");
        assertEquals(1, service.updateBizEpidemicTreatmentStandard(incoming));
        verify(mapper).updateBizEpidemicTreatmentStandard(argThat(r -> r.getKbSyncStatus() == 0));
    }

    @Test
    @DisplayName("已同步不可再次手动同步")
    void syncKbWhenAlreadySyncedThrows()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(5L);
        db.setPublishStatus(0);
        db.setKbSyncStatus(1);
        when(mapper.selectBizEpidemicTreatmentStandardById(5L)).thenReturn(db);

        assertThrows(ServiceException.class, () -> service.syncKb(5L));
        verify(mapper, never()).updateBizEpidemicTreatmentStandard(any());
    }

    @Test
    @DisplayName("删除：非未发布状态拒绝")
    void deleteRejectsNonDraftPublishStatus()
    {
        BizEpidemicTreatmentStandard db = baseRow();
        db.setId(30L);
        db.setPublishStatus(2);
        db.setKbSyncStatus(0);
        when(mapper.selectBizEpidemicTreatmentStandardById(30L)).thenReturn(db);

        assertThrows(ServiceException.class, () -> service.deleteBizEpidemicTreatmentStandardByIds(new Long[] { 30L }));
        verify(mapper, never()).deleteBizEpidemicTreatmentStandardById(anyLong());
    }

    private static BizEpidemicTreatmentStandard baseRow()
    {
        BizEpidemicTreatmentStandard r = new BizEpidemicTreatmentStandard();
        r.setStandardName("疫");
        r.setStandardType("001013");
        r.setIntroduction("");
        r.setContentFileUrl("http://localhost/f");
        r.setContentFilePath(Constants.RESOURCE_PREFIX + "/upload/2026/a.pdf");
        r.setContentFileName("a.pdf");
        return r;
    }
}
