/*
 * 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.persistence.jpa.outer;

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.Query;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
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.anyobject.ADynGroupMembership;
import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.group.TypeExtension;
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.persistence.jpa.AbstractTest;
import org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO;
import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADynGroupMembership;
import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDynGroupMembership;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

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

    @Autowired
    private AnyTypeDAO anyTypeDAO;

    @Autowired
    private AnyObjectDAO anyObjectDAO;

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private GroupDAO groupDAO;

    @Autowired
    private RealmDAO realmDAO;

    @Autowired
    private PlainSchemaDAO plainSchemaDAO;

    @Autowired
    private AnyTypeClassDAO anyTypeClassDAO;

    @Test
    public void saveWithTwoOwners() {
        assertThrows(InvalidEntityException.class, () -> {
            Group root = groupDAO.findByName("root");
            assertNotNull(root);

            User user = userDAO.findByUsername("rossini");
            assertNotNull(user);

            Group group = entityFactory.newEntity(Group.class);
            group.setRealm(realmDAO.getRoot());
            group.setName("error");
            group.setUserOwner(user);
            group.setGroupOwner(root);

            groupDAO.save(group);
        });
    }

    @Test
    public void findByOwner() {
        Group group = groupDAO.find("ebf97068-aa4b-4a85-9f01-680e8c4cf227");
        assertNotNull(group);

        User user = userDAO.find("823074dc-d280-436d-a7dd-07399fae48ec");
        assertNotNull(user);

        assertEquals(user, group.getUserOwner());

        List<Group> ownedGroups = groupDAO.findOwnedByUser(user.getKey());
        assertFalse(ownedGroups.isEmpty());
        assertEquals(1, ownedGroups.size());
        assertTrue(ownedGroups.contains(group));
    }

    @Test
    public void create() {
        Group group = entityFactory.newEntity(Group.class);
        group.setRealm(realmDAO.getRoot());
        group.setName("new");

        TypeExtension typeExt = entityFactory.newEntity(TypeExtension.class);
        typeExt.setAnyType(anyTypeDAO.findUser());
        typeExt.add(anyTypeClassDAO.find("csv"));
        typeExt.add(anyTypeClassDAO.find("other"));

        group.add(typeExt);
        typeExt.setGroup(group);

        groupDAO.save(group);

        entityManager().flush();

        group = groupDAO.findByName("new");
        assertNotNull(group);
        assertEquals(1, group.getTypeExtensions().size());
        assertEquals(2, group.getTypeExtension(anyTypeDAO.findUser()).get().getAuxClasses().size());
    }

    @Test
    public void createWithInternationalCharacters() {
        Group group = entityFactory.newEntity(Group.class);
        group.setName("räksmörgås");
        group.setRealm(realmDAO.findByFullPath(SyncopeConstants.ROOT_REALM));

        groupDAO.save(group);
        entityManager().flush();
    }

    @Test
    public void delete() {
        groupDAO.delete("b1f7c12d-ec83-441f-a50e-1691daaedf3b");

        entityManager().flush();

        assertNull(groupDAO.find("b1f7c12d-ec83-441f-a50e-1691daaedf3b"));
        assertEquals(userDAO.findAllGroups(userDAO.findByUsername("verdi")).size(), 2);
        assertNull(findPlainAttr("f82fc61f-8e74-4a4b-9f9e-b8a41f38aad9", GPlainAttr.class));
        assertNull(findPlainAttrValue("49f35879-2510-4f11-a901-24152f753538", GPlainAttrValue.class));
        assertNotNull(plainSchemaDAO.find("icon"));
    }

    /**
     * Static copy of {@link org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO} method with same signature:
     * required for avoiding creating of a new transaction - good for general use case but bad for the way how
     * this test class is architected.
     */
    @SuppressWarnings("unchecked")
    public List<Group> findDynGroups(final User user) {
        Query query = entityManager().createNativeQuery(
                "SELECT group_id FROM " + JPAGroupDAO.UDYNMEMB_TABLE + " WHERE any_id=?");
        query.setParameter(1, user.getKey());

        List<Group> result = new ArrayList<>();
        query.getResultList().stream().map(resultKey -> resultKey instanceof Object[]
                ? (String) ((Object[]) resultKey)[0]
                : ((String) resultKey)).
                forEach(actualKey -> {
                    Group group = groupDAO.find(actualKey.toString());
                    if (group != null && !result.contains(group)) {
                        result.add(group);
                    }
                });
        return result;
    }

    @Test
    public void udynMembership() {
        // 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 attr = entityFactory.newEntity(UPlainAttr.class);
        attr.setOwner(user);
        attr.setSchema(plainSchemaDAO.find("cool"));
        attr.add("true", anyUtilsFactory.getInstance(AnyTypeKind.USER));
        user.add(attr);

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

        // 1. create group with dynamic membership
        Group group = entityFactory.newEntity(Group.class);
        group.setRealm(realmDAO.getRoot());
        group.setName("new");

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

        group.setUDynMembership(dynMembership);

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

        entityManager().flush();

        // 2. verify that dynamic membership is there
        actual = groupDAO.find(actual.getKey());
        assertNotNull(actual);
        assertNotNull(actual.getUDynMembership());
        assertNotNull(actual.getUDynMembership().getKey());
        assertEquals(actual, actual.getUDynMembership().getGroup());

        // 3. verify that expected users have the created group dynamically assigned
        List<String> members = groupDAO.findUDynMembers(actual);
        assertEquals(2, members.size());
        assertEquals(Set.of("c9b2dec2-00a7-4855-97c0-d854842b4b24", newUserKey),
                new HashSet<>(members));

        user = userDAO.findByUsername("bellini");
        assertNotNull(user);
        Collection<Group> dynGroupMemberships = findDynGroups(user);
        assertEquals(1, dynGroupMemberships.size());
        assertTrue(dynGroupMemberships.contains(actual.getUDynMembership().getGroup()));

        // 4. delete the new user and verify that dynamic membership was updated
        userDAO.delete(newUserKey);

        entityManager().flush();

        actual = groupDAO.find(actual.getKey());
        members = groupDAO.findUDynMembers(actual);
        assertEquals(1, members.size());
        assertEquals("c9b2dec2-00a7-4855-97c0-d854842b4b24", members.get(0));

        // 5. delete group and verify that dynamic membership was also removed
        String dynMembershipKey = actual.getUDynMembership().getKey();

        groupDAO.delete(actual);

        entityManager().flush();

        assertNull(entityManager().find(JPAUDynGroupMembership.class, dynMembershipKey));

        dynGroupMemberships = findDynGroups(user);
        assertTrue(dynGroupMemberships.isEmpty());
    }

    /**
     * Static copy of {@link org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO} method with same signature:
     * required for avoiding creating of a new transaction - good for general use case but bad for the way how
     * this test class is architected.
     */
    @SuppressWarnings("unchecked")
    public List<Group> findDynGroups(final AnyObject anyObject) {
        Query query = entityManager().createNativeQuery(
                "SELECT group_id FROM " + JPAGroupDAO.ADYNMEMB_TABLE + " WHERE any_id=?");
        query.setParameter(1, anyObject.getKey());

        List<Group> result = new ArrayList<>();
        query.getResultList().stream().map(resultKey -> resultKey instanceof Object[]
                ? (String) ((Object[]) resultKey)[0]
                : ((String) resultKey)).
                forEach(actualKey -> {
                    Group group = groupDAO.find(actualKey.toString());
                    if (group != null && !result.contains(group)) {
                        result.add(group);
                    }
                });
        return result;
    }

    @Test
    public void adynMembership() {
        // 0. create any object matching the condition below
        AnyObject anyObject = entityFactory.newEntity(AnyObject.class);
        anyObject.setName("name");
        anyObject.setType(anyTypeDAO.find("PRINTER"));
        anyObject.setRealm(realmDAO.findByFullPath("/even/two"));

        APlainAttr attr = entityFactory.newEntity(APlainAttr.class);
        attr.setOwner(anyObject);
        attr.setSchema(plainSchemaDAO.find("model"));
        attr.add("Canon MFC8030", anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT));
        anyObject.add(attr);

        anyObject = anyObjectDAO.save(anyObject);
        String newAnyObjectKey = anyObject.getKey();
        assertNotNull(newAnyObjectKey);

        // 1. create group with dynamic membership
        Group group = entityFactory.newEntity(Group.class);
        group.setRealm(realmDAO.getRoot());
        group.setName("new");

        ADynGroupMembership dynMembership = entityFactory.newEntity(ADynGroupMembership.class);
        dynMembership.setAnyType(anyTypeDAO.find("PRINTER"));
        dynMembership.setFIQLCond("model==Canon MFC8030");
        dynMembership.setGroup(group);

        group.add(dynMembership);

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

        entityManager().flush();

        // 2. verify that dynamic membership is there
        actual = groupDAO.find(actual.getKey());
        assertNotNull(actual);
        assertNotNull(actual.getADynMembership(anyTypeDAO.find("PRINTER")).get());
        assertNotNull(actual.getADynMembership(anyTypeDAO.find("PRINTER")).get().getKey());
        assertEquals(actual, actual.getADynMembership(anyTypeDAO.find("PRINTER")).get().getGroup());

        // 3. verify that expected any objects have the created group dynamically assigned
        List<String> members = groupDAO.findADynMembers(actual).stream().filter(object
                -> "PRINTER".equals(anyObjectDAO.find(object).getType().getKey())).collect(Collectors.toList());
        assertEquals(2, members.size());
        assertEquals(
                Set.of("fc6dbc3a-6c07-4965-8781-921e7401a4a5", newAnyObjectKey),
                new HashSet<>(members));

        anyObject = anyObjectDAO.find("fc6dbc3a-6c07-4965-8781-921e7401a4a5");
        assertNotNull(anyObject);
        Collection<Group> dynGroupMemberships = findDynGroups(anyObject);
        assertEquals(1, dynGroupMemberships.size());
        assertTrue(dynGroupMemberships.contains(actual.getADynMembership(anyTypeDAO.find("PRINTER")).get().getGroup()));

        // 4. delete the new any object and verify that dynamic membership was updated
        anyObjectDAO.delete(newAnyObjectKey);

        entityManager().flush();

        actual = groupDAO.find(actual.getKey());
        members = groupDAO.findADynMembers(actual).stream().filter(object
                -> "PRINTER".equals(anyObjectDAO.find(object).getType().getKey())).collect(Collectors.toList());
        assertEquals(1, members.size());
        assertEquals("fc6dbc3a-6c07-4965-8781-921e7401a4a5", members.get(0));

        // 5. delete group and verify that dynamic membership was also removed
        String dynMembershipKey = actual.getADynMembership(anyTypeDAO.find("PRINTER")).get().getKey();

        groupDAO.delete(actual);

        entityManager().flush();

        assertNull(entityManager().find(JPAADynGroupMembership.class, dynMembershipKey));

        dynGroupMemberships = findDynGroups(anyObject);
        assertTrue(dynGroupMemberships.isEmpty());
    }

    @Test
    public void issueSYNCOPE1512() {
        Group group = groupDAO.findByName("root");
        assertNotNull(group);

        // non unique
        GPlainAttr title = entityFactory.newEntity(GPlainAttr.class);
        title.setOwner(group);
        title.setSchema(plainSchemaDAO.find("title"));
        title.add("syncope's group", anyUtilsFactory.getInstance(AnyTypeKind.GROUP));
        group.add(title);

        // unique
        GPlainAttr originalName = entityFactory.newEntity(GPlainAttr.class);
        originalName.setOwner(group);
        originalName.setSchema(plainSchemaDAO.find("originalName"));
        originalName.add("syncope's group", anyUtilsFactory.getInstance(AnyTypeKind.GROUP));
        group.add(originalName);

        groupDAO.save(group);

        entityManager().flush();

        group = groupDAO.find(group.getKey());
        assertEquals("syncope's group", group.getPlainAttr("title").get().getValuesAsStrings().get(0));
        assertEquals("syncope's group", group.getPlainAttr("originalName").get().getValuesAsStrings().get(0));
    }
}
