package tech.easyflow.ai.service.impl;

import com.easyagents.core.model.embedding.EmbeddingModel;
import com.easyagents.core.store.DocumentStore;
import com.easyagents.core.store.StoreOptions;
import com.easyagents.core.store.StoreResult;
import com.easyagents.search.engine.service.DocumentSearcher;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import tech.easyflow.ai.entity.DocumentChunk;
import tech.easyflow.ai.entity.DocumentCollection;
import tech.easyflow.ai.entity.Model;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.List;

/**
 * {@link DocumentServiceImpl} 外部索引回滚回归测试。
 */
public class DocumentServiceImplRollbackTest {

    /**
     * 验证手动导入回滚会检查关键词索引批量删除结果。
     *
     * @throws Exception 反射调用异常
     */
    @Test
    public void rollbackStoredChunksShouldReportKeywordDeleteFailure() throws Exception {
        DocumentServiceImpl service = new DocumentServiceImpl();
        DocumentStore documentStore = Mockito.mock(DocumentStore.class);
        DocumentSearcher searcher = Mockito.mock(DocumentSearcher.class);
        StoreOptions options = StoreOptions.ofCollectionName("knowledge-test");
        Mockito.when(documentStore.delete(Mockito.anyCollection(), Mockito.same(options)))
            .thenReturn(StoreResult.success());
        Mockito.when(searcher.deleteDocuments(Mockito.anyCollection())).thenReturn(false);

        DocumentCollection knowledge = new DocumentCollection();
        knowledge.setId(BigInteger.valueOf(901));
        Class<?> contextClass = Class.forName(
            DocumentServiceImpl.class.getName() + "$StoreExecutionContext"
        );
        Constructor<?> constructor = contextClass.getDeclaredConstructor(
            DocumentCollection.class,
            Model.class,
            EmbeddingModel.class,
            DocumentStore.class,
            StoreOptions.class,
            DocumentSearcher.class
        );
        constructor.setAccessible(true);
        Object context = constructor.newInstance(
            knowledge, null, null, documentStore, options, searcher);

        DocumentChunk chunk = new DocumentChunk();
        chunk.setId(BigInteger.valueOf(902));
        Method method = DocumentServiceImpl.class.getDeclaredMethod(
            "rollbackStoredChunks",
            contextClass,
            List.class
        );
        method.setAccessible(true);

        Object rollbackResult = method.invoke(service, context, List.of(chunk));

        Assert.assertEquals(Boolean.FALSE, rollbackResult);
        Mockito.verify(searcher).deleteDocuments(List.of(chunk.getId()));
    }

    /**
     * 验证手动导入会在外部索引回滚失败时追加明确处置提示。
     *
     * @throws Exception 反射调用异常
     */
    @Test
    public void buildStoreFailureMessageShouldIncludeRollbackFailure() throws Exception {
        DocumentServiceImpl service = new DocumentServiceImpl();
        Method method = DocumentServiceImpl.class.getDeclaredMethod(
            "buildStoreFailureMessage",
            String.class,
            Exception.class,
            boolean.class
        );
        method.setAccessible(true);

        String message = (String) method.invoke(
            service,
            "提交导入失败：",
            new IllegalStateException("关键词索引写入失败"),
            false
        );

        Assert.assertEquals(
            "提交导入失败：关键词索引写入失败；外部索引回滚未完成，请联系管理员处理",
            message
        );
    }
}
