package io.aiven.klaw.service;

import static io.aiven.klaw.error.KlawErrorMessages.ACL_ERR_101;
import static io.aiven.klaw.error.KlawErrorMessages.ACL_ERR_107;
import static io.aiven.klaw.error.KlawErrorMessages.ACL_ERR_108;
import static io.aiven.klaw.service.MailUtils.MailType.ACL_REQUESTED;
import static io.aiven.klaw.service.MailUtils.MailType.ACL_REQUEST_APPROVAL_ADDED;
import static io.aiven.klaw.service.MailUtils.MailType.ACL_REQUEST_APPROVED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.beans.BeanUtils.copyProperties;

import io.aiven.klaw.UtilMethods;
import io.aiven.klaw.config.ManageDatabase;
import io.aiven.klaw.dao.Acl;
import io.aiven.klaw.dao.AclRequests;
import io.aiven.klaw.dao.Approval;
import io.aiven.klaw.dao.Env;
import io.aiven.klaw.dao.KwClusters;
import io.aiven.klaw.dao.ServiceAccounts;
import io.aiven.klaw.dao.Team;
import io.aiven.klaw.dao.Topic;
import io.aiven.klaw.dao.UserInfo;
import io.aiven.klaw.error.KlawBadRequestException;
import io.aiven.klaw.error.KlawException;
import io.aiven.klaw.helpers.Pager;
import io.aiven.klaw.helpers.db.rdbms.HandleDbRequestsJdbc;
import io.aiven.klaw.model.ApiResponse;
import io.aiven.klaw.model.enums.AclIPPrincipleType;
import io.aiven.klaw.model.enums.AclPatternType;
import io.aiven.klaw.model.enums.AclType;
import io.aiven.klaw.model.enums.ApiResultStatus;
import io.aiven.klaw.model.enums.ApprovalType;
import io.aiven.klaw.model.enums.KafkaFlavors;
import io.aiven.klaw.model.enums.PermissionType;
import io.aiven.klaw.model.enums.RequestEntityType;
import io.aiven.klaw.model.enums.RequestOperationType;
import io.aiven.klaw.model.enums.RequestStatus;
import io.aiven.klaw.model.requests.AclRequestsModel;
import io.aiven.klaw.model.response.AclRequestsResponseModel;
import io.aiven.klaw.model.response.ServiceAccountDetails;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.util.ReflectionTestUtils;

@ExtendWith(SpringExtension.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AclControllerServiceTest {

  public static final int TENANT_ID = 101;
  private UtilMethods utilMethods;
  @Mock private UserDetails userDetails;
  @Mock private ClusterApiService clusterApiService;
  @Mock private HandleDbRequestsJdbc handleDbRequests;
  @Mock private ManageDatabase manageDatabase;
  @Mock private CommonUtilsService commonUtilsService;
  @Mock private RolesPermissionsControllerService rolesPermissionsControllerService;
  @Mock private MailUtils mailService;
  @Mock private UserInfo userInfo;
  @Mock private Pager pager;
  @Mock private ApprovalService approvalService;

  private AclControllerService aclControllerService;

  @Captor private ArgumentCaptor<AclRequests> aclRequestsCapture;

  @Captor private ArgumentCaptor<Team> teamCapture;

  @BeforeEach
  public void setUp() throws Exception {
    utilMethods = new UtilMethods();
    this.aclControllerService = new AclControllerService(clusterApiService, mailService);

    Env env = new Env();
    env.setName("DEV");
    env.setId("1");
    env.setClusterId(1);
    ReflectionTestUtils.setField(aclControllerService, "manageDatabase", manageDatabase);
    ReflectionTestUtils.setField(aclControllerService, "commonUtilsService", commonUtilsService);
    ReflectionTestUtils.setField(aclControllerService, "approvalService", approvalService);
    ReflectionTestUtils.setField(
        aclControllerService,
        "rolesPermissionsControllerService",
        rolesPermissionsControllerService);
    when(manageDatabase.getHandleDbRequests()).thenReturn(handleDbRequests);
    when(commonUtilsService.getEnvDetails(anyString(), anyInt())).thenReturn(env);
    when(commonUtilsService.getPrincipal()).thenReturn(userDetails);
    when(commonUtilsService.isNotAuthorizedUser(any(), any(PermissionType.class))).thenReturn(true);
  }

  private void mockKafkaFlavor() {
    Map<Integer, KwClusters> kwClustersMap = new HashMap<>();
    KwClusters kwClusters = new KwClusters();
    kwClusters.setKafkaFlavor(KafkaFlavors.APACHE_KAFKA.value);
    kwClusters.setProjectName("project");
    kwClusters.setServiceName("service");
    kwClusters.setClusterId(1);
    kwClustersMap.put(1, kwClusters);
    when(manageDatabase.getClusters(any(), anyInt())).thenReturn(kwClustersMap);
    when(manageDatabase.getKafkaEnvList(anyInt())).thenReturn(utilMethods.getEnvLists());
  }

  private void mockKafkaFlavorAiven() {
    Map<Integer, KwClusters> kwClustersMap = new HashMap<>();
    KwClusters kwClusters = new KwClusters();
    kwClusters.setKafkaFlavor(KafkaFlavors.AIVEN_FOR_APACHE_KAFKA.value);
    kwClusters.setProjectName("project");
    kwClusters.setServiceName("service");
    kwClusters.setClusterId(1);
    kwClustersMap.put(1, kwClusters);
    when(manageDatabase.getClusters(any(), anyInt())).thenReturn(kwClustersMap);
    when(manageDatabase.getKafkaEnvList(anyInt())).thenReturn(utilMethods.getEnvLists());
  }

  @Test
  @Order(1)
  public void createAclProducer() throws KlawException {
    AclRequests aclRequestsDao = new AclRequests();
    AclRequestsModel aclRequests = getAclRequestProducer();
    copyProperties(aclRequests, aclRequestsDao);
    List<Topic> topicList = utilMethods.getTopics();
    Map<String, String> hashMap = new HashMap<>();
    hashMap.put("result", ApiResultStatus.SUCCESS.value);
    when(commonUtilsService.getTopicsForTopicName(anyString(), anyInt())).thenReturn(topicList);
    when(handleDbRequests.requestForAcl(any())).thenReturn(hashMap);
    Env env = new Env();
    env.setClusterId(1);
    when(commonUtilsService.getEnvDetails(anyString(), anyInt())).thenReturn(env);
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);
    stubUserInfo();
    mockKafkaFlavor();

    ApiResponse resultResp = aclControllerService.createAcl(aclRequests);
    assertThat(resultResp.getMessage()).isEqualTo(ApiResultStatus.SUCCESS.value);
  }

  @Test
  @Order(2)
  public void createAclConsumer() throws KlawException {
    AclRequests aclRequestsDao = new AclRequests();
    AclRequestsModel aclRequests = getAclRequestConsumer();
    copyProperties(aclRequests, aclRequestsDao);
    List<Topic> topicList = utilMethods.getTopics();
    Map<String, String> hashMap = new HashMap<>();
    hashMap.put("result", ApiResultStatus.SUCCESS.value);
    when(commonUtilsService.getTopicsForTopicName(anyString(), anyInt())).thenReturn(topicList);
    when(handleDbRequests.requestForAcl(any())).thenReturn(hashMap);
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);

    mockKafkaFlavor();
    stubUserInfo();

    ApiResponse resultResp = aclControllerService.createAcl(aclRequests);
    assertThat(resultResp.getMessage()).isEqualTo(ApiResultStatus.SUCCESS.value);
  }

  @Test
  @Order(3)
  public void createAclConsumerThrowError() {
    AclRequests aclRequestsDao = new AclRequests();
    AclRequestsModel aclRequests = getAclRequestConsumer();
    copyProperties(aclRequests, aclRequestsDao);
    List<Topic> topicList = utilMethods.getTopics();
    when(commonUtilsService.getTopicsForTopicName(anyString(), anyInt())).thenReturn(topicList);
    when(handleDbRequests.requestForAcl(any()))
        .thenThrow(new RuntimeException("Failure in creating request"));
    stubUserInfo();
    mockKafkaFlavor();
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);

    KlawException thrown =
        Assertions.assertThrows(
            KlawException.class, () -> aclControllerService.createAcl(aclRequests));
    assertThat(thrown.getMessage()).isEqualTo("Failure in creating request");
  }

  @Test
  @Order(4)
  public void createAclNotAuthorized() throws KlawException {
    AclRequests aclRequestsDao = new AclRequests();
    AclRequestsModel aclRequests = getAclRequestProducer();
    copyProperties(aclRequests, aclRequestsDao);
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(true);
    stubUserInfo();

    ApiResponse resultResp = aclControllerService.createAcl(aclRequests);
    assertThat(resultResp.getMessage()).isEqualTo(ApiResultStatus.NOT_AUTHORIZED.value);
  }

  @Test
  @Order(5)
  public void createAclTopicNotFound() throws KlawException {
    AclRequests aclRequestsDao = new AclRequests();
    AclRequestsModel aclRequests = getAclRequestProducer();
    copyProperties(aclRequests, aclRequestsDao);
    when(handleDbRequests.getTopics(anyString(), anyInt())).thenReturn(Collections.emptyList());
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);
    stubUserInfo();

    ApiResponse resultResp = aclControllerService.createAcl(aclRequests);
    assertThat(resultResp.getMessage())
        .isEqualTo("Failure : Topic not found on target environment.");
  }

  @Test
  @Order(6)
  public void createAclInvalidPattern() throws KlawException {
    AclRequests aclRequestsDao = new AclRequests();
    AclRequestsModel aclRequestsModel = getAclRequestConsumer();
    aclRequestsModel.setAclPatternType(AclPatternType.PREFIXED.value);
    List<Topic> topicList = utilMethods.getTopics();
    copyProperties(aclRequestsModel, aclRequestsDao);
    when(handleDbRequests.getTopics(anyString(), anyInt())).thenReturn(topicList);
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);
    stubUserInfo();
    mockKafkaFlavor();

    ApiResponse resultResp = aclControllerService.createAcl(aclRequestsModel);
    assertThat(resultResp.getMessage())
        .isEqualTo("Failure : Please change the pattern to LITERAL for topic type.");
  }

  @Test
  @Order(7)
  public void createAclConsumerFailure() throws KlawException {
    AclRequests aclRequestsDao = new AclRequests();
    AclRequestsModel aclRequestsModel = getAclRequestConsumer();
    copyProperties(aclRequestsModel, aclRequestsDao);
    List<Topic> topicList = utilMethods.getTopics();
    Acl acl = new Acl();
    acl.setConsumergroup(aclRequestsModel.getConsumergroup());

    when(commonUtilsService.getTopicsForTopicName(anyString(), anyInt())).thenReturn(topicList);
    when(handleDbRequests.validateIfConsumerGroupUsedByAnotherTeam(anyInt(), anyInt(), anyString()))
        .thenReturn(true);
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);
    stubUserInfo();
    mockKafkaFlavor();

    ApiResponse resultResp = aclControllerService.createAcl(aclRequestsModel);
    assertThat(resultResp.getMessage())
        .isEqualTo(
            "Failure : Consumer group "
                + aclRequestsModel.getConsumergroup()
                + " used by another team.");
  }

  @Test
  @Order(8)
  public void createAclProducerEmptyTxnId() throws KlawException {
    AclRequests aclRequestsDao = new AclRequests();
    AclRequestsModel aclRequestsModel = getAclRequestProducer();
    aclRequestsModel.setTransactionalId("    "); // empty spaces
    copyProperties(aclRequestsModel, aclRequestsDao);
    List<Topic> topicList = utilMethods.getTopics();
    Map<String, String> hashMap = new HashMap<>();
    hashMap.put("result", ApiResultStatus.SUCCESS.value);
    when(commonUtilsService.getTopicsForTopicName(anyString(), anyInt())).thenReturn(topicList);
    when(handleDbRequests.requestForAcl(any())).thenReturn(hashMap);
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);
    stubUserInfo();
    mockKafkaFlavor();

    aclControllerService.createAcl(aclRequestsModel);
    assertThat(aclRequestsModel.getTransactionalId()).isEmpty();
  }

  @Test
  @Order(9)
  public void createAclMultipleAcls() {
    AclRequestsModel aclRequestsModel = getAclRequestProducer();
    AclRequests aclRequestsDao = new AclRequests();

    aclControllerService.handleIpAddressAndCNString(aclRequestsModel, aclRequestsDao);
    assertThat(aclRequestsDao.getAcl_ip())
        .isEqualTo(
            aclRequestsModel.getAcl_ip().get(0) + "<ACL>" + aclRequestsModel.getAcl_ip().get(1));
    assertThat(aclRequestsDao.getAcl_ssl()).isEqualTo("User:*");

    aclRequestsModel.setAclIpPrincipleType(AclIPPrincipleType.PRINCIPAL);
    aclRequestsModel.setAcl_ssl(new ArrayList<>(List.of("CN=abc", "CN=def")));
    aclControllerService.handleIpAddressAndCNString(aclRequestsModel, aclRequestsDao);
    assertThat(aclRequestsDao.getAcl_ssl())
        .isEqualTo(
            aclRequestsModel.getAcl_ssl().get(0) + "<ACL>" + aclRequestsModel.getAcl_ssl().get(1));
    assertThat(aclRequestsDao.getAcl_ip()).isNull();
  }

  @Test
  @Order(10)
  public void getAclRequestsFirstAndSecondPage() {
    String teamName = "teamname";
    List<Topic> topicList = getTopicList();
    List<UserInfo> userList = getUserInfoList();

    stubUserInfo();
    when(commonUtilsService.getTenantId(userDetails.getUsername())).thenReturn(1);
    when(manageDatabase.getKafkaEnvList(anyInt())).thenReturn(utilMethods.getEnvLists());
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(handleDbRequests.getAllAclRequests(
            anyBoolean(),
            anyString(),
            anyString(),
            anyString(),
            anyBoolean(),
            eq(null),
            eq(null),
            eq(null),
            eq(null),
            eq(null),
            eq(false),
            anyInt()))
        .thenReturn(getAclRequests("testtopic", 15));
    when(rolesPermissionsControllerService.getApproverRoles(anyString(), anyInt()))
        .thenReturn(Collections.singleton("USER"));
    when(manageDatabase.getTeamNameFromTeamId(anyInt(), anyInt())).thenReturn(teamName);
    when(commonUtilsService.getTopicsForTopicName(anyString(), anyInt())).thenReturn(topicList);
    when(handleDbRequests.getAllUsersInfoForTeam(anyInt(), anyInt())).thenReturn(userList);

    List<AclRequestsResponseModel> aclReqs =
        aclControllerService.getAclRequests(
            "1",
            "1",
            "all",
            null,
            null,
            null,
            null,
            null,
            io.aiven.klaw.model.enums.Order.ASC_REQUESTED_TIME,
            false);
    assertThat(aclReqs).hasSize(10);
    assertThat(aclReqs.get(0).getAcl_ip()).hasSize(3);
    assertThat(aclReqs.get(0).getTeamname()).isEqualTo(teamName);

    aclReqs =
        aclControllerService.getAclRequests(
            "2",
            "2",
            "all",
            null,
            null,
            null,
            null,
            null,
            io.aiven.klaw.model.enums.Order.ASC_REQUESTED_TIME,
            false);
    assertThat(aclReqs).hasSize(5);
    assertThat(aclReqs.get(0).getApprovingTeamDetails()).contains(userList.get(0).getUsername());
    assertThat(aclReqs.get(0).getApprovingTeamDetails()).contains(userList.get(1).getUsername());
  }

  @Test
  @Order(11)
  public void getCreatedAclRequests() {
    String teamName = "teamname";
    stubUserInfo();
    when(manageDatabase.getKafkaEnvList(anyInt())).thenReturn(utilMethods.getEnvLists());
    when(handleDbRequests.getCreatedAclRequestsByStatus(
            anyString(),
            anyString(),
            anyBoolean(),
            eq(RequestOperationType.CREATE),
            any(),
            any(),
            any(),
            any(),
            anyInt()))
        .thenReturn(getAclRequests("testtopic", 16));
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(manageDatabase.getTeamNameFromTeamId(anyInt(), anyInt())).thenReturn(teamName);

    List<AclRequestsResponseModel> listReqs =
        aclControllerService.getAclRequestsForApprover(
            "1",
            "1",
            "",
            null,
            null,
            RequestOperationType.CREATE,
            null,
            null,
            io.aiven.klaw.model.enums.Order.ASC_REQUESTED_TIME);
    assertThat(listReqs).hasSize(10);
  }

  @Test
  @Order(12)
  public void getCreatedAclRequestsNotAuthorizedForAllTeams() {
    String teamName = "teamname";
    stubUserInfo();
    when(manageDatabase.getKafkaEnvList(anyInt())).thenReturn(utilMethods.getEnvLists());
    when(handleDbRequests.getCreatedAclRequestsByStatus(
            anyString(),
            anyString(),
            anyBoolean(),
            eq(RequestOperationType.CREATE),
            any(),
            any(),
            any(),
            any(),
            anyInt()))
        .thenReturn(getAclRequests("testtopic", 16));
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.APPROVE_ALL_REQUESTS_TEAMS))
        .thenReturn(true);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(manageDatabase.getTeamNameFromTeamId(anyInt(), anyInt())).thenReturn(teamName);

    List<AclRequestsResponseModel> listReqs =
        aclControllerService.getAclRequestsForApprover(
            "1",
            "1",
            "",
            null,
            null,
            RequestOperationType.CREATE,
            null,
            null,
            io.aiven.klaw.model.enums.Order.ASC_REQUESTED_TIME);
    assertThat(listReqs).hasSize(10);
  }

  @Test
  @Order(13)
  public void deleteAclRequests() throws KlawException {
    String req_no = "1001";
    when(mailService.getCurrentUserName()).thenReturn("testuser");
    when(commonUtilsService.getTenantId(userDetails.getUsername())).thenReturn(1);
    when(handleDbRequests.deleteAclRequest(anyInt(), anyString(), anyInt()))
        .thenReturn(ApiResultStatus.SUCCESS.value);
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);
    ApiResponse result = aclControllerService.deleteAclRequests(req_no);
    assertThat(result.getMessage()).isEqualTo(ApiResultStatus.SUCCESS.value);
  }

  @Test
  @Order(14)
  public void deleteAclRequestsNotAuthorized() throws KlawException {
    String req_no = "1001";
    ApiResponse result = aclControllerService.deleteAclRequests(req_no);
    assertThat(result.getMessage()).isEqualTo(ApiResultStatus.NOT_AUTHORIZED.value);
  }

  @Test
  @Order(15)
  public void deleteAclRequestsFailure() {
    String req_no = "1001";
    when(mailService.getCurrentUserName()).thenReturn("testuser");
    when(handleDbRequests.deleteAclRequest(anyInt(), anyString(), anyInt()))
        .thenThrow(new RuntimeException("failure in deleting request"));
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_CREATE_SUBSCRIPTIONS))
        .thenReturn(false);
    KlawException thrown =
        Assertions.assertThrows(
            KlawException.class, () -> aclControllerService.deleteAclRequests(req_no));
    assertThat(thrown.getMessage()).isEqualTo("failure in deleting request");
  }

  @Test
  @Order(16)
  public void approveAclRequests() throws KlawException, KlawBadRequestException {
    AclRequests aclReq = getAclRequestDao();

    stubUserInfo();
    when(handleDbRequests.getAclRequest(anyInt(), anyInt())).thenReturn(aclReq);

    ApiResponse apiResponse = ApiResponse.SUCCESS;
    when(clusterApiService.approveAclRequests(any(), anyInt()))
        .thenReturn(new ResponseEntity<>(apiResponse, HttpStatus.OK));
    when(handleDbRequests.updateAclRequest(any(), any(), anyMap(), anyBoolean()))
        .thenReturn(ApiResultStatus.SUCCESS.value);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(commonUtilsService.isNotAuthorizedUser(userDetails, PermissionType.APPROVE_SUBSCRIPTIONS))
        .thenReturn(false);
    Topic t1 = new Topic();
    t1.setTopicname("testtopic");
    t1.setEnvironment("1");
    when(manageDatabase.getTopicsForTenant(anyInt())).thenReturn(List.of(t1));

    ApiResponse apiResp = aclControllerService.approveAclRequests("112");
    assertThat(apiResp.isSuccess()).isTrue();
  }

  @Test
  @Order(17)
  public void approveAclRequestsWithAivenAcl() throws KlawException, KlawBadRequestException {
    AclRequests aclReq = getAclRequestDao();

    stubUserInfo();
    when(handleDbRequests.getAclRequest(anyInt(), anyInt())).thenReturn(aclReq);

    Map<String, String> dataObj = new HashMap<>();
    String aivenAclIdKey = "aivenaclid";
    dataObj.put(aivenAclIdKey, "abcdef"); // any test key

    ApiResponse apiResponse =
        ApiResponse.builder()
            .success(true)
            .message(ApiResultStatus.SUCCESS.value)
            .data(dataObj)
            .build();
    when(clusterApiService.approveAclRequests(any(), anyInt()))
        .thenReturn(new ResponseEntity<>(apiResponse, HttpStatus.OK));
    when(handleDbRequests.updateAclRequest(any(), any(), anyMap(), anyBoolean()))
        .thenReturn(ApiResultStatus.SUCCESS.value);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(commonUtilsService.isNotAuthorizedUser(userDetails, PermissionType.APPROVE_SUBSCRIPTIONS))
        .thenReturn(false);
    Topic t1 = new Topic();
    t1.setTopicname("testtopic");
    t1.setEnvironment("1");
    when(manageDatabase.getTopicsForTenant(anyInt())).thenReturn(List.of(t1));

    ApiResponse apiResp = aclControllerService.approveAclRequests("112");
    assertThat(apiResp.isSuccess()).isTrue();
  }

  @Test
  @Order(18)
  public void approveAclRequestsNotAuthorized() throws KlawException, KlawBadRequestException {
    stubUserInfo();
    ApiResponse apiResp = aclControllerService.approveAclRequests("112");
    assertThat(apiResp.getMessage()).isEqualTo(ApiResultStatus.NOT_AUTHORIZED.value);
  }

  @Test
  @Order(19)
  public void approveAclRequestsOwnRequest() throws KlawException, KlawBadRequestException {
    stubUserInfo();
    AclRequests aclReq = getAclRequestDao();
    aclReq.setRequestor("kwusera");
    when(handleDbRequests.getAclRequest(anyInt(), anyInt())).thenReturn(aclReq);
    when(commonUtilsService.isNotAuthorizedUser(userDetails, PermissionType.APPROVE_SUBSCRIPTIONS))
        .thenReturn(false);
    ApiResponse apiResp = aclControllerService.approveAclRequests("112");
    assertThat(apiResp.getMessage())
        .isEqualTo("You are not allowed to approve your own subscription requests.");
  }

  @Test
  @Order(20)
  public void approveAclRequestsFailure1() throws KlawException, KlawBadRequestException {
    String req_no = "1001";
    AclRequests aclReq = getAclRequestDao();
    stubUserInfo();
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(handleDbRequests.getAclRequest(anyInt(), anyInt())).thenReturn(aclReq);
    Topic t1 = new Topic();
    t1.setTopicname("testtopic");
    t1.setEnvironment("1");
    when(manageDatabase.getTopicsForTenant(anyInt())).thenReturn(List.of(t1));
    when(commonUtilsService.isNotAuthorizedUser(userDetails, PermissionType.APPROVE_SUBSCRIPTIONS))
        .thenReturn(false);

    ApiResponse apiResponse = ApiResponse.notOk("failure");
    when(clusterApiService.approveAclRequests(any(), anyInt()))
        .thenReturn(new ResponseEntity<>(apiResponse, HttpStatus.OK));

    ApiResponse apiResp = aclControllerService.approveAclRequests(req_no);
    assertThat(apiResp.getMessage()).isEqualTo("failure");
  }

  @Test
  @Order(21)
  public void approveAclRequestsFailure2() throws KlawException, KlawBadRequestException {
    String req_no = "1001";
    AclRequests aclReq = getAclRequestDao();

    stubUserInfo();
    when(handleDbRequests.getAclRequest(anyInt(), anyInt())).thenReturn(aclReq);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));

    Topic t1 = new Topic();
    t1.setTopicname("testtopic");
    t1.setEnvironment("1");
    when(manageDatabase.getTopicsForTenant(anyInt())).thenReturn(List.of(t1));

    ApiResponse apiResponse = ApiResponse.SUCCESS;
    when(clusterApiService.approveAclRequests(any(), anyInt()))
        .thenReturn(new ResponseEntity<>(apiResponse, HttpStatus.OK));
    when(handleDbRequests.updateAclRequest(any(), any(), anyMap(), anyBoolean()))
        .thenThrow(new RuntimeException("Error"));
    when(commonUtilsService.isNotAuthorizedUser(userDetails, PermissionType.APPROVE_SUBSCRIPTIONS))
        .thenReturn(false);

    ApiResponse apiResp = aclControllerService.approveAclRequests(req_no);
    assertThat(apiResp.getMessage()).isEqualTo("failure");
  }

  @Test
  @Order(22)
  public void approveAclRequestsFailure3() throws KlawException, KlawBadRequestException {
    String req_no = "1001";
    AclRequests aclReq = getAclRequestDao();
    aclReq.setRequestStatus(RequestStatus.APPROVED.value);

    stubUserInfo();
    when(handleDbRequests.getAclRequest(anyInt(), anyInt())).thenReturn(aclReq);
    when(manageDatabase.getTeamsAndAllowedEnvs(anyInt(), anyInt()))
        .thenReturn(Collections.singletonList("1"));
    when(commonUtilsService.isNotAuthorizedUser(userDetails, PermissionType.APPROVE_SUBSCRIPTIONS))
        .thenReturn(false);

    ApiResponse apiResp = aclControllerService.approveAclRequests(req_no);
    assertThat(apiResp.getMessage()).isEqualTo("This request does not exist anymore.");
  }

  @Test
  @Order(23)
  public void declineAclRequests() throws KlawException {
    String req_no = "1001";
    AclRequests aclReq = getAclRequestDao();

    stubUserInfo();
    when(handleDbRequests.getAclRequest(anyInt(), anyInt())).thenReturn(aclReq);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(handleDbRequests.declineAclRequest(any(), any()))
        .thenReturn(ApiResultStatus.SUCCESS.value);
    when(commonUtilsService.isNotAuthorizedUser(userDetails, PermissionType.APPROVE_SUBSCRIPTIONS))
        .thenReturn(false);

    ApiResponse resultResp = aclControllerService.declineAclRequests(req_no, "");
    assertThat(resultResp.getMessage()).isEqualTo(ApiResultStatus.SUCCESS.value);
  }

  @Test
  @Order(24)
  public void declineAclRequestsFailure() {
    String req_no = "1001";
    AclRequests aclReq = getAclRequestDao();

    stubUserInfo();
    when(handleDbRequests.getAclRequest(anyInt(), anyInt())).thenReturn(aclReq);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(commonUtilsService.isNotAuthorizedUser(userDetails, PermissionType.APPROVE_SUBSCRIPTIONS))
        .thenReturn(false);

    when(handleDbRequests.declineAclRequest(any(), anyString()))
        .thenThrow(new RuntimeException("failure in declining request"));
    KlawException thrown =
        Assertions.assertThrows(
            KlawException.class, () -> aclControllerService.declineAclRequests(req_no, "Reason"));
    assertThat(thrown.getMessage()).isEqualTo("failure in declining request");
  }

  @Test
  @Order(25)
  public void createDeleteAclSubscriptionRequest() throws KlawException {
    String reqNo = "101";
    stubUserInfo();
    Acl acl = utilMethods.getAllAcls().get(1);

    when(commonUtilsService.getTenantId(userDetails.getUsername())).thenReturn(1);
    when(commonUtilsService.getTeamId(anyString())).thenReturn(TENANT_ID);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(handleDbRequests.getSyncAclsFromReqNo(anyInt(), anyInt())).thenReturn(acl);
    Map<String, String> hashMap = new HashMap<>();
    hashMap.put("result", ApiResultStatus.SUCCESS.value);
    when(handleDbRequests.requestForAcl(any())).thenReturn(hashMap);
    when(commonUtilsService.isNotAuthorizedUser(
            userDetails, PermissionType.REQUEST_DELETE_SUBSCRIPTIONS))
        .thenReturn(false);

    ApiResponse resultResp = aclControllerService.createDeleteAclSubscriptionRequest(reqNo);
    assertThat(resultResp.getMessage()).isEqualTo(ApiResultStatus.SUCCESS.value);
  }

  @Test
  @Order(26)
  public void getAivenServiceAccountDetails() throws KlawException {
    String reqNo = "101";
    stubUserInfo();
    mockKafkaFlavor();
    ServiceAccountDetails serviceAccountDetails = new ServiceAccountDetails();
    serviceAccountDetails.setPassword("password");
    serviceAccountDetails.setUsername("username");
    serviceAccountDetails.setAccountFound(true);

    Acl acl = utilMethods.getAllAcls().get(1);

    when(commonUtilsService.getTenantId(userDetails.getUsername())).thenReturn(1);
    when(commonUtilsService.getTeamId(anyString())).thenReturn(TENANT_ID);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(handleDbRequests.getSyncAclsFromReqNo(anyInt(), anyInt())).thenReturn(acl);
    when(clusterApiService.getAivenServiceAccountDetails(
            anyString(), anyString(), anyString(), anyInt()))
        .thenReturn(serviceAccountDetails);

    ServiceAccountDetails resultResp =
        aclControllerService.getAivenServiceAccountDetails("1", "testtopic", "service", reqNo);

    assertThat(resultResp.isAccountFound()).isTrue();
  }

  @Test
  @Order(27)
  public void getAivenServiceAccountDetailsAccountDoesNotExist() throws KlawException {
    String reqNo = "101";
    stubUserInfo();
    mockKafkaFlavor();
    ServiceAccountDetails serviceAccountDetails = new ServiceAccountDetails();
    serviceAccountDetails.setAccountFound(false);

    Acl acl = utilMethods.getAllAcls().get(1);

    when(commonUtilsService.getTenantId(userDetails.getUsername())).thenReturn(1);
    when(commonUtilsService.getTeamId(anyString())).thenReturn(TENANT_ID);
    when(commonUtilsService.getEnvsFromUserId(anyString()))
        .thenReturn(new HashSet<>(Collections.singletonList("1")));
    when(handleDbRequests.getSyncAclsFromReqNo(anyInt(), anyInt())).thenReturn(acl);
    when(clusterApiService.getAivenServiceAccountDetails(
            anyString(), anyString(), anyString(), anyInt()))
        .thenReturn(serviceAccountDetails);

    ServiceAccountDetails resultResp =
        aclControllerService.getAivenServiceAccountDetails("1", "testtopic", "service", reqNo);

    assertThat(resultResp.isAccountFound()).isFalse();
  }

  @Test
  @Order(28)
  public void getAivenServiceAccounts() throws KlawException {
    stubUserInfo();
    mockKafkaFlavor();
    Set<String> serviceAccountInfoSet = new HashSet<>();
    serviceAccountInfoSet.add("user1");
    serviceAccountInfoSet.add("user2");

    ApiResponse apiResponse =
        ApiResponse.builder()
            .message(ApiResultStatus.SUCCESS.value)
            .data(serviceAccountInfoSet)
            .build();

    when(commonUtilsService.getTenantId(userDetails.getUsername())).thenReturn(1);
