/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.syncope.core.provisioning.java;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
import org.apache.syncope.core.persistence.api.entity.EntityFactory;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.user.LinkedAccount;
import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.MappingManager;
import org.identityconnectors.common.security.SecurityUtil;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeUtil;
import org.identityconnectors.framework.common.objects.OperationalAttributes;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;

@Transactional("Master")
public class DefaultMappingManagerTest extends AbstractTest {

    @Autowired
    private MappingManager mappingManager;

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private ExternalResourceDAO resourceDAO;

    @Autowired
    private RealmDAO realmDAO;

    @Autowired
    private GroupDAO groupDAO;

    @Autowired
    private AnyTypeClassDAO anyTypeClassDAO;

    @Autowired
    private PlainSchemaDAO plainSchemaDAO;

    @Autowired
    private AnyUtilsFactory anyUtilsFactory;

    @Autowired
    private EntityFactory entityFactory;

    @Test
    public void prepareAttrsForUser() {
        User bellini = userDAO.findByUsername("bellini");
        ExternalResource ldap = resourceDAO.find("resource-ldap");
        Provision provision = ldap.getProvision(AnyTypeKind.USER.name()).get();

        assertNotEquals(CipherAlgorithm.AES, bellini.getCipherAlgorithm());

        // 1. with clear-text password
        Pair<String, Set<Attribute>> attrs = mappingManager.prepareAttrsFromAny(
                bellini,
                "Password123",
                true,
                Boolean.TRUE,
                provision);
        assertEquals("bellini", attrs.getLeft());
        assertEquals(
                "uid=bellini,ou=people,o=isp",
                AttributeUtil.getNameFromAttributes(attrs.getRight()).getNameValue());
        assertEquals("Password123", SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs.getRight())));

        // 2. with changePwd == false
        attrs = mappingManager.prepareAttrsFromAny(
                bellini,
                "Password123",
                false,
                Boolean.TRUE,
                provision);
        assertNull(AttributeUtil.getPasswordValue(attrs.getRight()));

        // 3. with no clear-text password but random password generation enabled
        ldap.setRandomPwdIfNotProvided(true);
        ldap = resourceDAO.save(ldap);
        entityManager().flush();

        String encPassword = bellini.getPassword();
        attrs = mappingManager.prepareAttrsFromAny(
                bellini,
                null,
                true,
                Boolean.TRUE,
                provision);
        assertNotEquals(encPassword, SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs.getRight())));

        // 4. with no clear-text password and random password generation disabled
        ldap.setRandomPwdIfNotProvided(false);
        resourceDAO.save(ldap);
        entityManager().flush();

        attrs = mappingManager.prepareAttrsFromAny(
                bellini,
                null,
                true,
                Boolean.TRUE,
                provision);
        assertNull(AttributeUtil.getPasswordValue(attrs.getRight()));

        // 5. with no clear-text password, random password generation disabled but AES
        ReflectionTestUtils.setField(bellini, "cipherAlgorithm", CipherAlgorithm.AES);
        bellini.setPassword("newPassword123");
        userDAO.save(bellini);
        entityManager().flush();

        assertEquals(CipherAlgorithm.AES, bellini.getCipherAlgorithm());

        attrs = mappingManager.prepareAttrsFromAny(
                bellini,
                null,
                true,
                Boolean.TRUE,
                provision);
        assertEquals("newPassword123", SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs.getRight())));
    }

    @Test
    public void prepareAttrsForLinkedAccount() {
        User vivaldi = userDAO.findByUsername("vivaldi");
        ExternalResource ldap = resourceDAO.find("resource-ldap");
        Provision provision = ldap.getProvision(AnyTypeKind.USER.name()).get();

        LinkedAccount account = entityFactory.newEntity(LinkedAccount.class);
        account.setConnObjectKeyValue("admin");
        account.setResource(ldap);
        account.setOwner(vivaldi);
        account.setSuspended(Boolean.FALSE);
        account.setCipherAlgorithm(CipherAlgorithm.AES);
        account.setPassword("Password321");
        vivaldi.add(account);

        vivaldi = userDAO.save(vivaldi);
        entityManager().flush();

        // 1. with account password and clear-text default password
        Set<Attribute> attrs = mappingManager.prepareAttrsFromLinkedAccount(
                vivaldi,
                account,
                "Password123",
                true,
                provision);
        assertEquals("admin", AttributeUtil.getStringValue(AttributeUtil.find("cn", attrs)));
        assertEquals("Password321", SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs)));
        assertTrue(AttributeUtil.getBooleanValue(AttributeUtil.find(OperationalAttributes.ENABLE_NAME, attrs)));

        // 2. without account password and clear-text default password
        account.setEncodedPassword(null, null);

        attrs = mappingManager.prepareAttrsFromLinkedAccount(
                vivaldi,
                account,
                "Password123",
                true,
                provision);
        assertEquals("Password123", SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs)));

        // 3. with changePwd == false
        attrs = mappingManager.prepareAttrsFromLinkedAccount(
                vivaldi,
                account,
                "Password123",
                false,
                provision);
        assertNull(AttributeUtil.getPasswordValue(attrs));

        // 4. without account password, no clear-text password but random password generation enabled
        ldap.setRandomPwdIfNotProvided(true);
        ldap = resourceDAO.save(ldap);
        entityManager().flush();

        String encPassword = vivaldi.getPassword();
        attrs = mappingManager.prepareAttrsFromLinkedAccount(
                vivaldi,
                account,
                null,
                true,
                provision);
        assertNotEquals(encPassword, SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attrs)));

        // 5. without account password, no clear-text password and random password generation disabled
        ldap.setRandomPwdIfNotProvided(false);
        resourceDAO.save(ldap);
        entityManager().flush();

        attrs = mappingManager.prepareAttrsFromLinkedAccount(
                vivaldi,
                account,
                null,
                true,
                provision);
        assertNull(AttributeUtil.getPasswordValue(attrs));
    }

    @Test
    public void issueSYNCOPE1583() {
        // 0. create user matching the condition below
        User user = entityFactory.newEntity(User.class);
        user.setUsername("username");
        user.setRealm(realmDAO.findByFullPath("/even/two"));
        user.add(anyTypeClassDAO.find("other"));

        UPlainAttr cool = entityFactory.newEntity(UPlainAttr.class);
        cool.setOwner(user);
        cool.setSchema(plainSchemaDAO.find("cool"));
        cool.add("true", anyUtilsFactory.getInstance(AnyTypeKind.USER));
        user.add(cool);

        user = userDAO.save(user);
        String newUserKey = user.getKey();
        assertNotNull(newUserKey);

        // 1. update group with dynamic membership
        Group group = groupDAO.findByName("root");
        assertNotNull(group);

        UDynGroupMembership dynMembership = entityFactory.newEntity(UDynGroupMembership.class);
        dynMembership.setFIQLCond("cool==true");
        dynMembership.setGroup(group);
        group.setUDynMembership(dynMembership);

        group = groupDAO.saveAndRefreshDynMemberships(group);
        assertNotNull(group);

        entityManager().flush();

        // 2. verify that dynamic membership is in place
        assertTrue(userDAO.findAllGroupKeys(user).contains(group.getKey()));

        // 3. check propagation attrs
        ExternalResource csv = resourceDAO.find("resource-csv");
        Provision provision = csv.getProvision(AnyTypeKind.USER.name()).get();
        assertNotNull(provision);

        Pair<String, Set<Attribute>> attrs = mappingManager.prepareAttrsFromAny(
                user,
                null,
                false,
                Boolean.TRUE,
                provision);
        assertTrue(attrs.getRight().stream().anyMatch(
                attr -> "theirgroup".equals(attr.getName()) && List.of("sx-dx").equals(attr.getValue())));
    }
}
