content: package io.aiven.klaw.service;
  
  import static org.mockito.ArgumentMatchers.anyString;
  import static org.mockito.ArgumentMatchers.eq;
  import static org.mockito.Mockito.timeout;
  import static org.mockito.Mockito.when;
  
  import io.aiven.klaw.config.ManageDatabase;
  import io.aiven.klaw.dao.Team;
  import io.aiven.klaw.dao.UserInfo;
  import io.aiven.klaw.helpers.KwConstants;
  import io.aiven.klaw.helpers.db.rdbms.HandleDbRequestsJdbc;
  import io.aiven.klaw.model.enums.PermissionType;
  import io.aiven.klaw.service.MailUtils.MailType;
  import java.util.Collections;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.stream.Stream;
  import org.junit.jupiter.api.BeforeEach;
  import org.junit.jupiter.api.Test;
  import org.junit.jupiter.api.extension.ExtendWith;
  import org.junit.jupiter.params.ParameterizedTest;
  import org.junit.jupiter.params.provider.MethodSource;
  import org.mockito.InjectMocks;
  import org.mockito.Mock;
  import org.mockito.Mockito;
  import org.springframework.security.core.userdetails.UserDetails;
  import org.springframework.security.test.context.support.WithMockUser;
  import org.springframework.test.context.junit.jupiter.SpringExtension;
  
  @ExtendWith(SpringExtension.class)
  public class MailUtilsTest {
  
    public static final String LOGIN_URL = "https://localhost:9097";
    @Mock UserDetails userDetails;
  
    //  @Mock HandleDbRequests handleDbRequests;
  
    @Mock HandleDbRequestsJdbc handleDbRequestsJdbc;
  
    @Mock EmailService emailService;
  
    @Mock ManageDatabase manageDatabase;
  
    @InjectMocks private MailUtils mailService;
  
    @BeforeEach
    public void setUp() throws Exception {
      //    mailService = new MailUtils();
      when(manageDatabase.getHandleDbRequests()).thenReturn(handleDbRequestsJdbc);
      when(handleDbRequestsJdbc.getUsersInfo(eq("james")))
          .thenReturn(createUserInfo("James", "USER"));
      when(handleDbRequestsJdbc.getAllTeamsOfUsers(eq("James"), eq(101)))
          .thenReturn(List.of(createTeam("OpenSource", 5), createTeam("Octopus", 11)));
      when(manageDatabase.getRolesPermissionsPerTenant(eq(101)))
          .thenReturn(getRolesToPermissionsMap());
  
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.passwordreset.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicrequest.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicdeleterequest.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicclaimrequest.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicrequestapproval.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicrequestdenial.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.aclrequest.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.aclrequestdelete.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.aclrequestapproval.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.aclrequestdenial.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
    }
  
    @Test
    public void getUserDetails() {}
  
    @Test
    public void resetPasswordEmail_noCCTeam() throws InterruptedException {
  
      String username = "Octopus";
      UserInfo info = createUserInfo(username, "USER");
      when(manageDatabase.selectAllCachedUserInfo()).thenReturn(List.of(info));
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.passwordreset.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      mailService.sendMailResetPwd(username, "KlawPassword", handleDbRequestsJdbc, 101, LOGIN_URL);
  
      Thread.sleep(1000);
      Mockito.verify(emailService, timeout(1000).times(1))
          .sendSimpleMessage(
              eq(info.getMailid()), eq(null), anyString(), anyString(), eq(101), eq(LOGIN_URL));
    }
  
    @Test
    public void resetPasswordEmail_noSuchUser() {
  
      String username = "Octopus";
      UserInfo info = createUserInfo("Octi", "USER");
      when(manageDatabase.selectAllCachedUserInfo()).thenReturn(List.of(info));
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.passwordreset.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_PASSWORDRESET_CONTENT);
      mailService.sendMailResetPwd(username, "KlawPassword", handleDbRequestsJdbc, 101, LOGIN_URL);
      Mockito.verify(emailService, timeout(1000).times(0))
          .sendSimpleMessage(
              eq(info.getMailid()), eq(null), anyString(), anyString(), eq(101), eq(LOGIN_URL));
    }
  
    @Test
    @WithMockUser(
        username = "james",
        authorities = {"USER"})
    public void sendMailWith_NoBCC() {
      String username = "James";
      when(manageDatabase.selectAllCachedUserInfo())
          .thenReturn(List.of(createUserInfo(username, "USER"), createUserInfo("Tom", "ADMIN")));
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.aclrequestapproval.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_ACLREQUESTAPPROVAL_CONTENT);
  
      mailService.sendMail(
          "TopicOne",
          "AclOne",
          null,
          username,
          null,
          null,
          handleDbRequestsJdbc,
          MailType.ACL_REQUEST_APPROVED,
          LOGIN_URL);
  
      Mockito.verify(emailService, timeout(1000).times(1))
          .sendSimpleMessage(
              eq(List.of("James.klaw@mailid")),
              eq(List.of("OpenSource.klaw@mailid")),
              eq(Collections.emptyList()),
              anyString(),
              anyString(),
              eq(101),
              eq(LOGIN_URL));
    }
  
    @Test
    @WithMockUser(
        username = "james",
        authorities = {"USER"})
    public void sendMailWith_BCC() {
  
      String username = "James";
      when(manageDatabase.selectAllCachedUserInfo())
          .thenReturn(List.of(createUserInfo(username, "USER"), createUserInfo("Tom", "ADMIN")));
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicrequest.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_TOPICREQUEST_CONTENT);
  
      mailService.sendMail(
          "TopicOne",
          "AclOne",
          null,
          username,
          null,
          null,
          handleDbRequestsJdbc,
          MailType.TOPIC_CREATE_REQUESTED,
          LOGIN_URL);
  
      Mockito.verify(emailService, timeout(1000).times(1))
          .sendSimpleMessage(
              eq(List.of("OpenSource.klaw@mailid")), // to is to the approver team
              eq(List.of("James.klaw@mailid")), // cc is to the requester
              eq(List.of("Tom.klaw@mailid")), // bcc is to the user with the permission to approve all
              // requests.
              anyString(),
              anyString(),
              eq(101),
              eq(LOGIN_URL));
    }
  
    /** Tests all emails being sent for request for new resources */
    @WithMockUser(
        username = "james",
        authorities = {"USER"})
    @ParameterizedTest
    @MethodSource(value = "requestMailType")
    public void sendRequestEmail(MailType mailType) {
  
      String username = "James";
      when(manageDatabase.selectAllCachedUserInfo())
          .thenReturn(List.of(createUserInfo(username, "USER"), createUserInfo("Tom", "ADMIN")));
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicrequest.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_TOPICREQUEST_CONTENT);
  
      mailService.sendMail(
          "TopicOne",
          "AclOne",
          null,
          username,
          null,
          null,
          handleDbRequestsJdbc,
          mailType,
          LOGIN_URL);
  
      Mockito.verify(emailService, timeout(1000).times(1))
          .sendSimpleMessage(
              eq(List.of("OpenSource.klaw@mailid")), // to is to the approver team
              eq(List.of("James.klaw@mailid")), // cc is to the requester
              eq(List.of("Tom.klaw@mailid")), // bcc is to the user with the permission to approve all
              // requests.
              anyString(),
              anyString(),
              eq(101),
              eq(LOGIN_URL));
    }
  
    /** Test all emails being sent for notification of approvals */
    @WithMockUser(
        username = "james",
        authorities = {"USER"})
    @ParameterizedTest()
    @MethodSource(value = "approvedMailType")
    public void sendRequestApprovedEmail(MailType mailType) {
      String username = "James";
      when(manageDatabase.selectAllCachedUserInfo())
          .thenReturn(
              List.of(
                  createUserInfo(username, "USER"),
                  createUserInfo("Rob", "USER"),
                  createUserInfo("Tom", "ADMIN")));
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicrequest.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_TOPICREQUEST_CONTENT);
  
      mailService.sendMail(
          "TopicOne", "AclOne", "", username, "Rob", null, handleDbRequestsJdbc, mailType, LOGIN_URL);
  
      Mockito.verify(emailService, timeout(1000).times(1))
          .sendSimpleMessage(
              eq(List.of("James.klaw@mailid")), // to is to the requester & the requestors team
              eq(List.of("OpenSource.klaw@mailid", "Rob.klaw@mailid")), // cc is to the approver team
              eq(Collections.emptyList()), // bcc is empty
              // requests.
              anyString(),
              anyString(),
              eq(101),
              eq(LOGIN_URL));
    }
  
    /***
     * Tests all emails sent to claim a resource
     */
    @WithMockUser(
        username = "james",
        authorities = {"USER"})
    @ParameterizedTest()
    @MethodSource(value = "claimMailType")
    public void sendClaimRequestEmail(MailType mailType) {
  
      String username = "James";
      when(manageDatabase.selectAllCachedUserInfo())
          .thenReturn(
              List.of(
                  createUserInfo(username, "USER"),
                  createUserInfo("Rob", "USER"),
                  createUserInfo("Tom", "ADMIN")));
      when(manageDatabase.getKwPropertyValue(eq("klaw.mail.topicrequest.content"), eq(101)))
          .thenReturn(KwConstants.MAIL_TOPICREQUEST_CONTENT);
  
      when(handleDbRequestsJdbc.getTeamDetails(eq(11), eq(101)))
          .thenReturn(createTeam("Octopus", 11));
  
      mailService.sendMail(
          "TopicOne",
          "AclOne",
          "",
          username,
          "Rob",
          Integer.parseInt("11"),
          handleDbRequestsJdbc,
          mailType,
          LOGIN_URL);
  
      Mockito.verify(emailService, timeout(1000).times(1))
          .sendSimpleMessage(
              eq(
                  List.of(
                      "Octopus.klaw@mailid")), // to is to the approver team and if there is a contact
              // assigned to the resource
              eq(
                  List.of(
                      "OpenSource.klaw@mailid",
                      "James.klaw@mailid")), // cc is to the requester & the requestors team
              eq(List.of("Tom.klaw@mailid")), // bcc has thohse with special approval permissions.
              // requests.
              anyString(),
              anyString(),
              eq(101),
              eq(LOGIN_URL));
    }
  
    /** Tests all emails sent for notification of claim approval */
    private static Stream<MailType> requestMailType() {
      return Stream.of(
          MailType.CONNECTOR_CREATE_REQUESTED,
          MailType.CONNECTOR_DELETE_REQUESTED,
          MailType.SCHEMA_REQUESTED,
          MailType.TOPIC_DELETE_REQUESTED,
          MailType.TOPIC_CREATE_REQUESTED,
          MailType.ACL_REQUESTED,
          MailType.ACL_DELETE_REQUESTED);
    }
  
    private static Stream<MailType> approvedMailType() {
      return Stream.of(
          MailType.CONNECTOR_REQUEST_APPROVED,
          MailType.CONNECTOR_REQUEST_DENIED,
          MailType.SCHEMA_REQUEST_APPROVED,
          MailType.SCHEMA_REQUEST_DENIED,
          MailType.TOPIC_REQUEST_APPROVED,
          MailType.TOPIC_REQUEST_DENIED,
          MailType.ACL_REQUEST_DENIED,
          MailType.ACL_REQUEST_APPROVED,
          MailType.ACL_REQUEST_FAILURE);
    }
  
    private static Stream<MailType> claimMailType() {
      return Stream.of(MailType.CONNECTOR_CLAIM_REQUESTED, MailType.TOPIC_CLAIM_REQUESTED);
    }
  
    private Map<String, Set<String>> getRolesToPermissionsMap() {
  
      Set<String> user = Set.of(PermissionType.APPROVE_TOPICS.name());
  
      Set<String> admin =
          Set.of(
              PermissionType.APPROVE_TOPICS.name(), PermissionType.APPROVE_ALL_REQUESTS_TEAMS.name());
  
      return Map.of("USER", user, "ADMIN", admin);
    }
  
    private static UserInfo createUserInfo(String username, String role) {
      UserInfo info = new UserInfo();
      info.setUsername(username);
      info.setMailid(username + ".klaw@mailid");
      info.setTenantId(101);
      info.setTeamId(10);
      info.setRole(role);
      return info;
    }
  
    private static Team createTeam(String teamName, int teamId) {
      Team t = new Team();
      t.setTeamId(teamId);
      t.setTeammail(teamName + ".klaw@mailid");
      t.setTeamname(teamName);
      return t;
    }
  }
  