package tech.easyflow.agent.runtime.composer;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import tech.easyflow.agent.config.AgentMediaProperties;
import tech.easyflow.agent.runtime.media.AgentMediaService;
import tech.easyflow.common.entity.LoginAccount;

import java.math.BigInteger;
import java.util.List;

/**
 * {@link AgentComposerDraftService} 草稿清理测试。
 */
public class AgentComposerDraftServiceTest {

    private static final String DRAFT_KEY = "easyflow:agent:composer:draft:2:7:FORMAL:9:101";
    private static final String ACTIVE_KEY = "easyflow:agent:composer:active:2:7:FORMAL:9";

    private StringRedisTemplate redisTemplate;
    private ValueOperations<String, String> valueOperations;
    private AgentMediaService mediaService;
    private AgentComposerDraftService service;
    private LoginAccount account;

    /**
     * 初始化草稿服务测试依赖。
     */
    @Before
    @SuppressWarnings("unchecked")
    public void setUp() {
        redisTemplate = Mockito.mock(StringRedisTemplate.class);
        valueOperations = Mockito.mock(ValueOperations.class);
        Mockito.when(redisTemplate.opsForValue()).thenReturn(valueOperations);
        mediaService = Mockito.mock(AgentMediaService.class);
        service = new AgentComposerDraftService(redisTemplate, new ObjectMapper(),
                new AgentMediaProperties(), mediaService);
        account = new LoginAccount();
        account.setTenantId(BigInteger.valueOf(2));
        account.setId(BigInteger.valueOf(7));
    }

    /**
     * 验证删除草稿时合并服务端与调用方上传 ID 并清理临时图片。
     *
     * @throws Exception JSON 编码失败时抛出
     */
    @Test
    public void deleteShouldCleanupDraftUploadsBeforeRedisKeys() throws Exception {
        AgentComposerDraft draft = new AgentComposerDraft();
        draft.setImageUploadIds(List.of("upload-1", "upload-2"));
        Mockito.when(valueOperations.get(DRAFT_KEY))
                .thenReturn(new ObjectMapper().writeValueAsString(draft));
        Mockito.when(valueOperations.get(ACTIVE_KEY)).thenReturn("101");

        service.delete("FORMAL", "9", "101", List.of("upload-2", "upload-3"), true, account);

        Mockito.verify(mediaService).deleteUploadsForScope(
                List.of("upload-1", "upload-2", "upload-3"), "FORMAL", "9", "101", account);
        Mockito.verify(redisTemplate).delete(List.of(DRAFT_KEY,
                "easyflow:agent:composer:revision:2:7:FORMAL:9:101"));
        Mockito.verify(redisTemplate).delete(ACTIVE_KEY);
    }

    /**
     * 验证关闭上传清理时只删除草稿缓存。
     */
    @Test
    public void deleteShouldKeepUploadsWhenCleanupIsDisabled() {
        Mockito.when(valueOperations.get(ACTIVE_KEY)).thenReturn("101");

        service.delete("FORMAL", "9", "101", List.of("upload-1"), false, account);

        Mockito.verifyNoInteractions(mediaService);
        Mockito.verify(redisTemplate).delete(List.of(DRAFT_KEY,
                "easyflow:agent:composer:revision:2:7:FORMAL:9:101"));
    }

    /**
     * 验证旧版草稿未保存图片 ID 字段时仍能完成清理。
     *
     * @throws Exception JSON 编码失败时抛出
     */
    @Test
    public void deleteShouldHandleLegacyDraftWithoutImageUploadIds() throws Exception {
        AgentComposerDraft draft = new AgentComposerDraft();
        Mockito.when(valueOperations.get(DRAFT_KEY))
                .thenReturn(new ObjectMapper().writeValueAsString(draft));

        service.delete("FORMAL", "9", "101", List.of(), true, account);

        Mockito.verify(mediaService).deleteUploadsForScope(
                List.of(), "FORMAL", "9", "101", account);
        Mockito.verify(redisTemplate).delete(List.of(DRAFT_KEY,
                "easyflow:agent:composer:revision:2:7:FORMAL:9:101"));
    }
}
