/*
 * 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.fit.core;

import static org.junit.jupiter.api.Assertions.assertEquals;
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 static org.junit.jupiter.api.Assertions.fail;

import java.security.AccessControlException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.audit.AuditEntry;
import org.apache.syncope.common.lib.request.UserCR;
import org.apache.syncope.common.lib.to.AuditConfTO;
import org.apache.syncope.common.lib.to.DelegationTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.common.lib.types.AuditLoggerName;
import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.rest.api.beans.AnyQuery;
import org.apache.syncope.common.rest.api.beans.AuditQuery;
import org.apache.syncope.common.rest.api.service.DelegationService;
import org.apache.syncope.common.rest.api.service.UserService;
import org.apache.syncope.core.logic.UserLogic;
import org.apache.syncope.fit.AbstractITCase;
import org.junit.jupiter.api.Test;

public class DelegationITCase extends AbstractITCase {

    private DelegationTO create(final DelegationService ds, final DelegationTO delegation) {
        Response response = ds.create(delegation);
        if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
            Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
            if (ex != null) {
                throw (RuntimeException) ex;
            }
        }
        return getObject(response.getLocation(), DelegationService.class, DelegationTO.class);
    }

    @Test
    public void crudAsAdmin() {
        // 1. create users        
        UserCR delegatingCR = UserITCase.getUniqueSample("delegating@syncope.apache.org");
        delegatingCR.getRoles().add("User reviewer");
        UserTO delegating = createUser(delegatingCR).getEntity();
        assertNotNull(delegating.getKey());

        UserCR delegatedCR = UserITCase.getUniqueSample("delegated@syncope.apache.org");
        UserTO delegated = createUser(delegatedCR).getEntity();
        assertNotNull(delegated.getKey());

        DelegationTO delegation = new DelegationTO();
        delegation.setDelegating(delegating.getKey());
        delegation.setDelegated(delegated.getKey());

        // no dates set -> FAIL
        try {
            delegationService.create(delegation);
            fail();
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.InvalidEntity, e.getType());
        }

        delegation.setStart(new Date());
        delegation.setEnd(new Date(System.currentTimeMillis() - 1000));

        // end before start -> FAIL
        try {
            delegationService.create(delegation);
            fail();
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.InvalidEntity, e.getType());
        }

        delegation.setEnd(new Date());

        // 2. create delegation
        delegation = create(delegationService, delegation);
        assertNotNull(delegation.getKey());
        assertNotNull(delegation.getEnd());

        // 3. verify delegation is reported for users
        delegating = userService.read(delegating.getKey());
        assertEquals(List.of(delegation.getKey()), delegating.getDelegatingDelegations());
        assertEquals(List.of(), delegating.getDelegatedDelegations());

        delegated = userService.read(delegated.getKey());
        assertEquals(List.of(), delegated.getDelegatingDelegations());
        assertEquals(List.of(delegation.getKey()), delegated.getDelegatedDelegations());

        // 4. update and read delegation
        delegation.setEnd(null);
        delegationService.update(delegation);

        delegation = delegationService.read(delegation.getKey());
        assertNull(delegation.getEnd());

        // 5. delete delegation
        delegationService.delete(delegation.getKey());

        try {
            delegationService.read(delegation.getKey());
            fail();
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.NotFound, e.getType());
        }

        // 6. verify delegation is not reported for users
        delegating = userService.read(delegating.getKey());
        assertEquals(List.of(), delegating.getDelegatingDelegations());
        assertEquals(List.of(), delegating.getDelegatedDelegations());

        delegated = userService.read(delegated.getKey());
        assertEquals(List.of(), delegated.getDelegatingDelegations());
        assertEquals(List.of(), delegated.getDelegatedDelegations());
    }

    @Test
    public void crudAsUser() {
        // 1. create users        
        UserCR delegatingCR = UserITCase.getUniqueSample("delegating@syncope.apache.org");
        delegatingCR.getRoles().add("User reviewer");
        UserTO delegating = createUser(delegatingCR).getEntity();
        assertNotNull(delegating.getKey());

        UserCR delegatedCR = UserITCase.getUniqueSample("delegated@syncope.apache.org");
        UserTO delegated = createUser(delegatedCR).getEntity();
        assertNotNull(delegated.getKey());

        DelegationTO delegation = new DelegationTO();
        delegation.setDelegating("c9b2dec2-00a7-4855-97c0-d854842b4b24");
        delegation.setDelegated(delegated.getKey());
        delegation.setStart(new Date());

        DelegationService uds = clientFactory.create(delegating.getUsername(), "password123").
                getService(DelegationService.class);

        // delegating user is not requesting user -> FAIL
        try {
            create(uds, delegation);
            fail();
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
        }

        // 2. create delegation
        delegation.setDelegating(delegating.getKey());

        delegation = create(uds, delegation);
        assertNotNull(delegation.getKey());
        assertNull(delegation.getEnd());

        // 3. update and read delegation
        delegation.setEnd(new Date());
        uds.update(delegation);

        delegation = uds.read(delegation.getKey());
        assertNotNull(delegation.getEnd());

        // 4. delete delegation
        uds.delete(delegation.getKey());

        try {
            uds.read(delegation.getKey());
            fail();
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.NotFound, e.getType());
        }
    }

    @Test
    public void operations() {
        // 0. enable audit
        AuditLoggerName authLoginSuccess = new AuditLoggerName(
                AuditElements.EventCategoryType.LOGIC,
                UserLogic.class.getSimpleName(),
                null,
                "search",
                AuditElements.Result.SUCCESS);
        AuditConfTO authLogin = new AuditConfTO();
        authLogin.setKey(authLoginSuccess.toAuditKey());
        authLogin.setActive(true);
        auditService.create(authLogin);

        // 1. bellini delegates rossini
        DelegationTO delegation = new DelegationTO();
        delegation.setDelegating("bellini");
        delegation.setDelegated("rossini");
        delegation.setStart(new Date());
        delegation = create(delegationService, delegation);
        assertNotNull(delegation.getKey());

        // 2. search users as bellini
        SyncopeClient bellini = clientFactory.create("bellini", "password");
        int forBellini = bellini.getService(UserService.class).search(
                new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).build()).getTotalCount();

        SyncopeClient rossini = clientFactory.create("rossini", "password");

        // 3. search users as rossini
        Triple<Map<String, Set<String>>, List<String>, UserTO> self = rossini.self();
        assertEquals(List.of("bellini"), self.getMiddle());

        // 3a. search users as rossini without delegation -> FAIL
        try {
            rossini.getService(UserService.class).search(
                    new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).build());
            fail();
        } catch (ForbiddenException e) {
            assertNotNull(e);
        }

        // 3b. search users as rossini with delegation -> SUCCESS
        int forRossini = rossini.delegatedBy("bellini").getService(UserService.class).search(
                new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).build()).getTotalCount();
        assertEquals(forBellini, forRossini);

        // 4. delete delegation: searching users as rossini does not work, even with delegation
        delegationService.delete(delegation.getKey());

        try {
            rossini.getService(UserService.class).search(
                    new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).build());
            fail();
        } catch (AccessControlException e) {
            assertNotNull(e);
        }

        // 5. query audit entries
        AuditQuery query = new AuditQuery.Builder().
                type(authLoginSuccess.getType()).
                category(authLoginSuccess.getCategory()).
                event(authLoginSuccess.getEvent()).
                result(authLoginSuccess.getResult()).
                build();
        List<AuditEntry> entries = query(query, MAX_WAIT_SECONDS);
        assertTrue(entries.stream().anyMatch(entry -> "rossini [delegated by bellini]".equals(entry.getWho())));

        // 6. disable audit
        authLogin.setActive(false);
        auditService.update(authLogin);
    }
}
