package com.infoepoch.pms.agent.domain.care.orchestrator;

import com.infoepoch.pms.agent.domain.care.model.CareConversationState;
import com.infoepoch.pms.agent.domain.care.model.CareQuery;
import com.infoepoch.pms.agent.domain.care.model.CareTaskType;
import com.infoepoch.pms.agent.domain.care.model.PagedResult;
import com.infoepoch.pms.agent.domain.care.model.UserProfileSummary;
import com.infoepoch.pms.agent.domain.care.state.CareConversationStateService;
import com.infoepoch.pms.agent.domain.care.stream.CareStreamingResponseAssembler;
import com.infoepoch.pms.agent.properties.CareAgentProperties;
import com.infoepoch.pms.agent.tool.union.care.UserSearchTool;
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 reactor.test.StepVerifier;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class UserRecommendationExecutorTest {

    @Mock
    private UserSearchTool userSearchTool;

    @Mock
    private CareConversationStateService conversationStateService;

    private UserRecommendationExecutor executor;

    @BeforeEach
    void setUp() {
        CareAgentProperties properties = new CareAgentProperties();
        properties.setUserPageSize(100);
        properties.setUserStreamItemDelayMillis(250);
        executor = new UserRecommendationExecutor(
                userSearchTool,
                conversationStateService,
                new CareStreamingResponseAssembler(),
                properties
        );
    }

    @Test
    void shouldKeepDifferentUsersWhenNameMatchesButMobileDiffers() {
        CareQuery query = new CareQuery(
                CareTaskType.RECOMMEND_USERS,
                2,
                false,
                "推荐用户",
                "健步走",
                "推荐用户",
                Map.of(),
                ""
        );
        when(userSearchTool.execute(eq("trace-1"), eq("session-1"), anyMap(), eq(1), anyInt()))
                .thenReturn(new PagedResult<>(
                        List.of(
                                user("user:zhang-138", "张三", "13800000000"),
                                user("user:zhang-139", "张三", "13900000000")
                        ),
                        2,
                        false
                ));

        StepVerifier.withVirtualTime(() -> executor.execute("trace-1", "session-1", query, null))
                .expectSubscription()
                .expectNextMatches(chunk -> chunk.contains("### 用户推荐"))
                .expectNoEvent(Duration.ofMillis(249))
                .thenAwait(Duration.ofMillis(1))
                .expectNextMatches(chunk -> chunk.contains("1. **张三**"))
                .expectNoEvent(Duration.ofMillis(249))
                .thenAwait(Duration.ofMillis(1))
                .expectNextMatches(chunk -> chunk.contains("2. **张三**"))
                .expectNoEvent(Duration.ofMillis(249))
                .thenAwait(Duration.ofMillis(1))
                .expectNextMatches(chunk -> chunk.contains("如需继续补充更多用户"))
                .verifyComplete();

        ArgumentCaptor<CareConversationState> captor = ArgumentCaptor.forClass(CareConversationState.class);
        verify(conversationStateService).save(captor.capture());
        assertEquals(Set.of("user:zhang-138", "user:zhang-139"), captor.getValue().deliveredIds());
    }

    @Test
    void shouldDeduplicateUsersWhenNameAndMobileBothMatch() {
        CareQuery query = new CareQuery(
                CareTaskType.RECOMMEND_USERS,
                2,
                true,
                "再来一些",
                "健步走",
                "推荐用户",
                Map.of(),
                ""
        );
        CareConversationState state = new CareConversationState(
                "session-1",
                CareTaskType.RECOMMEND_USERS,
                2,
                "健步走",
                "推荐用户",
                Map.of(),
                2,
                Set.of("user:zhang-138"),
                LocalDateTime.now()
        );
        when(userSearchTool.execute(eq("trace-1"), eq("session-1"), anyMap(), eq(2), anyInt()))
                .thenReturn(new PagedResult<>(
                        List.of(
                                user("user:zhang-138", "张三", "13800000000"),
                                user("user:li-139", "李四", "13900000000")
                        ),
                        2,
                        false
                ));

        StepVerifier.withVirtualTime(() -> executor.execute("trace-1", "session-1", query, state))
                .expectSubscription()
                .expectNextMatches(chunk -> chunk.contains("### 用户推荐"))
                .expectNoEvent(Duration.ofMillis(249))
                .thenAwait(Duration.ofMillis(1))
                .expectNextMatches(chunk -> chunk.contains("1. **李四**"))
                .expectNoEvent(Duration.ofMillis(249))
                .thenAwait(Duration.ofMillis(1))
                .expectNextMatches(chunk -> chunk.contains("目前先为你整理到这些更匹配的用户"))
                .verifyComplete();

        ArgumentCaptor<CareConversationState> captor = ArgumentCaptor.forClass(CareConversationState.class);
        verify(conversationStateService).save(captor.capture());
        assertEquals(Set.of("user:zhang-138", "user:li-139"), captor.getValue().deliveredIds());
    }

    private UserProfileSummary user(String userId, String name, String mobile) {
        return new UserProfileSummary(
                userId,
                name,
                65,
                "男",
                List.of(),
                List.of(),
                "部门A",
                "手机号：" + mobile
        );
    }
}
