package com.infoepoch.pms.agent.service.auth;

import com.infoepoch.pms.agent.domain.baisc.user.User;
import com.infoepoch.pms.agent.domain.baisc.user.UserCriteria;
import com.infoepoch.pms.agent.domain.baisc.user.UserQueryService;
import com.infoepoch.pms.agent.platform.shared.exception.BusinessException;
import com.infoepoch.pms.agent.service.auth.dto.LoginSessionUser;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class TargetUserServiceTest {

    private UserQueryService userQueryService;
    private TargetUserService targetUserService;

    @BeforeEach
    void setUp() {
        userQueryService = mock(UserQueryService.class);
        targetUserService = new TargetUserService(userQueryService);
    }

    @Test
    void matchesEnabledUserByUsername() {
        when(userQueryService.popupListNotRela(argThat(this::matchesZhangsanCriteria)))
                .thenReturn(List.of(user("user-1", "zhangsan", false)));

        LoginSessionUser loginSessionUser = targetUserService.findLoginSessionUser("zhangsan");

        assertThat(loginSessionUser.getUserId()).isEqualTo("user-1");
        assertThat(loginSessionUser.getUsername()).isEqualTo("zhangsan");
        assertThat(loginSessionUser.getFullname()).isEqualTo("张三");
        assertThat(loginSessionUser.getOrganizationId()).isEqualTo("org-1");
        assertThat(loginSessionUser.getOrganizationName()).isEqualTo("组织一");
    }

    @Test
    void rejectsMissingUser() {
        when(userQueryService.popupListNotRela(argThat(this::matchesZhangsanCriteria)))
                .thenReturn(List.of());

        assertThatThrownBy(() -> targetUserService.findLoginSessionUser("zhangsan"))
                .isInstanceOf(BusinessException.class)
                .hasMessageContaining("目标系统不存在该用户");
    }

    @Test
    void rejectsDuplicateUser() {
        when(userQueryService.popupListNotRela(argThat(this::matchesZhangsanCriteria)))
                .thenReturn(List.of(
                        user("user-1", "zhangsan", false),
                        user("user-2", "zhangsan", false)
                ));

        assertThatThrownBy(() -> targetUserService.findLoginSessionUser("zhangsan"))
                .isInstanceOf(BusinessException.class)
                .hasMessageContaining("目标系统用户匹配不唯一");
    }

    @Test
    void rejectsDisabledUserEvenIfReturnedByRepository() {
        when(userQueryService.popupListNotRela(argThat(this::matchesZhangsanCriteria)))
                .thenReturn(List.of(user("user-1", "zhangsan", true)));

        assertThatThrownBy(() -> targetUserService.findLoginSessionUser("zhangsan"))
                .isInstanceOf(BusinessException.class)
                .hasMessageContaining("目标系统用户已禁用");
    }

    private boolean matchesZhangsanCriteria(UserCriteria criteria) {
        return criteria != null
                && criteria.getUsernameList().equals(List.of("zhangsan"))
                && Boolean.FALSE.equals(criteria.isDisabled());
    }

    private User user(String id, String username, boolean disabled) {
        User user = new User();
        user.setId(id);
        user.setUsername(username);
        user.setFullname("张三");
        user.setOrganizationId("org-1");
        user.setOrganizationName("组织一");
        user.setDisabled(disabled);
        return user;
    }
}
