/*
 * 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.assertFalse;
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 com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import org.apache.cxf.jaxrs.client.Client;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.request.AnyObjectCR;
import org.apache.syncope.common.lib.to.AnyObjectTO;
import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.ProvisioningReport;
import org.apache.syncope.common.lib.to.PullTaskTO;
import org.apache.syncope.common.lib.to.PushTaskTO;
import org.apache.syncope.common.lib.to.ReconStatus;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.MatchType;
import org.apache.syncope.common.lib.types.ResourceOperation;
import org.apache.syncope.common.lib.types.UnmatchingRule;
import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.common.rest.api.beans.AnyQuery;
import org.apache.syncope.common.rest.api.beans.CSVPullSpec;
import org.apache.syncope.common.rest.api.beans.CSVPushSpec;
import org.apache.syncope.common.rest.api.beans.ReconQuery;
import org.apache.syncope.common.rest.api.service.ReconciliationService;
import org.apache.syncope.fit.AbstractITCase;
import org.identityconnectors.framework.common.objects.OperationalAttributes;
import org.identityconnectors.framework.common.objects.Uid;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.core.JdbcTemplate;

public class ReconciliationITCase extends AbstractITCase {

    @Test
    public void push() {
        // 1. create printer, with no resources
        AnyObjectCR printerCR = AnyObjectITCase.getSample("reconciliation");
        printerCR.getResources().clear();
        AnyObjectTO printer = createAnyObject(printerCR).getEntity();
        assertNotNull(printer.getKey());

        // 2. verify no printer with that name is on the external resource's db
        JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
        assertEquals(0, jdbcTemplate.queryForList(
                "SELECT id FROM testPRINTER WHERE printername=?", printer.getName()).size());

        // 3. verify reconciliation status
        ReconStatus status = RECONCILIATION_SERVICE.status(
                new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).anyKey(printer.getName()).build());
        assertNotNull(status);
        assertEquals(AnyTypeKind.ANY_OBJECT, status.getAnyTypeKind());
        assertEquals(printer.getKey(), status.getAnyKey());
        assertEquals(MatchType.ANY, status.getMatchType());
        assertNotNull(status.getOnSyncope());
        assertNull(status.getOnResource());

        // 4. push
        PushTaskTO pushTask = new PushTaskTO();
        pushTask.setPerformCreate(true);
        pushTask.setUnmatchingRule(UnmatchingRule.PROVISION);
        RECONCILIATION_SERVICE.push(new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).
                anyKey(printer.getKey()).build(), pushTask);

        // 5. verify that printer is now propagated
        assertEquals(1, jdbcTemplate.queryForList(
                "SELECT id FROM testPRINTER WHERE printername=?", printer.getName()).size());

        // 6. verify resource was not assigned
        printer = ANY_OBJECT_SERVICE.read(printer.getKey());
        assertTrue(printer.getResources().isEmpty());

        // 7. verify reconciliation status
        status = RECONCILIATION_SERVICE.status(
                new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).anyKey(printer.getName()).build());
        assertNotNull(status);
        assertNotNull(status.getOnSyncope());
        assertNotNull(status.getOnResource());

        // __ENABLE__ management depends on the actual connector...
        Attr enable = status.getOnSyncope().getAttr(OperationalAttributes.ENABLE_NAME).orElse(null);
        if (enable != null) {
            status.getOnSyncope().getAttrs().remove(enable);
        }
        // FIQL is always null for Syncope
        assertNull(status.getOnSyncope().getFiql());
        assertNotNull(status.getOnResource().getFiql());
        status.getOnResource().setFiql(null);
        assertEquals(status.getOnSyncope(), status.getOnResource());
    }

    @Test
    public void pull() {
        // 1. create printer, with no resources
        AnyObjectCR printerCR = AnyObjectITCase.getSample("reconciliation");
        printerCR.getResources().clear();
        AnyObjectTO printer = createAnyObject(printerCR).getEntity();
        assertNotNull(printer.getKey());
        assertNotEquals("Nowhere", printer.getPlainAttr("location").get().getValues().get(0));

        // 2. add row into the external resource's table, with same name
        JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
        jdbcTemplate.update(
                "INSERT INTO TESTPRINTER (id, printername, location, deleted, lastmodification) VALUES (?,?,?,?,?)",
                printer.getKey(), printer.getName(), "Nowhere", false, new Date());

        // 3. verify reconciliation status
        ReconStatus status = RECONCILIATION_SERVICE.status(
                new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).anyKey(printer.getName()).build());
        assertNotNull(status);
        assertNotNull(status.getOnSyncope());
        assertNotNull(status.getOnResource());
        assertNotEquals(status.getOnSyncope().getAttr("LOCATION"), status.getOnResource().getAttr("LOCATION"));

        // 4. pull
        PullTaskTO pullTask = new PullTaskTO();
        pullTask.setDestinationRealm(SyncopeConstants.ROOT_REALM);
        pullTask.setPerformUpdate(true);
        RECONCILIATION_SERVICE.pull(new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).
                anyKey(printer.getName()).build(), pullTask);

        // 5. verify reconciliation result (and resource is still not assigned)
        printer = ANY_OBJECT_SERVICE.read(printer.getKey());
        assertEquals("Nowhere", printer.getPlainAttr("location").get().getValues().get(0));
        assertTrue(printer.getResources().isEmpty());
    }

    @Test
    public void importSingle() {
        // 1. add row into the external resource's table
        String externalKey = UUID.randomUUID().toString();
        String externalName = "printer" + getUUIDString();

        JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
        jdbcTemplate.update(
                "INSERT INTO TESTPRINTER (id, printername, location, deleted, lastmodification) VALUES (?,?,?,?,?)",
                externalKey, externalName, "Nowhere", false, new Date());

        // 2. verify reconciliation status
        ReconStatus status = RECONCILIATION_SERVICE.status(
                new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).fiql("ID==" + externalKey).build());
        assertNotNull(status);
        assertNull(status.getAnyTypeKind());
        assertNull(status.getAnyKey());
        assertNull(status.getMatchType());
        assertNull(status.getOnSyncope());
        assertNotNull(status.getOnResource());
        assertEquals(externalKey, status.getOnResource().getAttr(Uid.NAME).get().getValues().get(0));
        assertEquals(externalName, status.getOnResource().getAttr("PRINTERNAME").get().getValues().get(0));

        // 3. pull
        PullTaskTO pullTask = new PullTaskTO();
        pullTask.setDestinationRealm(SyncopeConstants.ROOT_REALM);
        pullTask.setPerformCreate(true);
        RECONCILIATION_SERVICE.pull(
                new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).fiql("ID==" + externalKey).build(), pullTask);

        // 4. verify reconciliation result
        AnyObjectTO printer = ANY_OBJECT_SERVICE.read(externalName);
        assertNotNull(printer);
    }

    @Test
    public void importCSV() {
        ReconciliationService service = ADMIN_CLIENT.getService(ReconciliationService.class);
        Client client = WebClient.client(service);
        client.type(RESTHeaders.TEXT_CSV);

        CSVPullSpec spec = new CSVPullSpec.Builder(AnyTypeKind.USER.name(), "username").build();
        InputStream csv = getClass().getResourceAsStream("/test1.csv");

        List<ProvisioningReport> results = service.pull(spec, csv);
        assertEquals(AnyTypeKind.USER.name(), results.get(0).getAnyType());
        assertNotNull(results.get(0).getKey());
        assertEquals("donizetti", results.get(0).getName());
        assertEquals("donizetti", results.get(0).getUidValue());
        assertEquals(ResourceOperation.CREATE, results.get(0).getOperation());
        assertEquals(ProvisioningReport.Status.SUCCESS, results.get(0).getStatus());

        UserTO donizetti = USER_SERVICE.read(results.get(0).getKey());
        assertNotNull(donizetti);
        assertEquals("Gaetano", donizetti.getPlainAttr("firstname").get().getValues().get(0));
        assertEquals(1, donizetti.getPlainAttr("loginDate").get().getValues().size());

        UserTO cimarosa = USER_SERVICE.read(results.get(1).getKey());
        assertNotNull(cimarosa);
        assertEquals("Domenico Cimarosa", cimarosa.getPlainAttr("fullname").get().getValues().get(0));
        assertEquals(2, cimarosa.getPlainAttr("loginDate").get().getValues().size());
    }

    @Test
    public void exportCSV() throws IOException {
        ReconciliationService service = ADMIN_CLIENT.getService(ReconciliationService.class);
        Client client = WebClient.client(service);
        client.accept(RESTHeaders.TEXT_CSV);

        AnyQuery anyQuery = new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
                fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("*ini").query()).
                page(1).
                size(1000).
                orderBy("username ASC").
                build();

        CSVPushSpec spec = new CSVPushSpec.Builder(AnyTypeKind.USER.name()).ignorePaging(true).
                field("username").
                field("status").
                plainAttr("firstname").
                plainAttr("surname").
                plainAttr("email").
                plainAttr("loginDate").
                build();

        Response response = service.push(anyQuery, spec);
        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
        assertEquals(
                "attachment; filename=" + SyncopeConstants.MASTER_DOMAIN + ".csv",
                response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION));

        PagedResult<UserTO> users = USER_SERVICE.search(anyQuery);
        assertNotNull(users);

        MappingIterator<Map<String, String>> reader = new CsvMapper().readerFor(Map.class).
                with(CsvSchema.emptySchema().withHeader()).readValues((InputStream) response.getEntity());

        int rows = 0;
        for (; reader.hasNext(); rows++) {
            Map<String, String> row = reader.next();

            assertEquals(users.getResult().get(rows).getUsername(), row.get("username"));
            assertEquals(users.getResult().get(rows).getStatus(), row.get("status"));

            switch (row.get("username")) {
                case "rossini":
                    assertEquals(spec.getNullValue(), row.get("email"));
                    assertTrue(row.get("loginDate").contains(spec.getArrayElementSeparator()));
                    break;

                case "verdi":
                    assertEquals("verdi@syncope.org", row.get("email"));
                    assertEquals(spec.getNullValue(), row.get("loginDate"));
                    break;

                case "bellini":
                    assertEquals(spec.getNullValue(), row.get("email"));
                    assertFalse(row.get("loginDate").contains(spec.getArrayElementSeparator()));
                    break;

                default:
                    break;
            }
        }
        assertEquals(rows, users.getTotalCount());
    }
}
