/*
 * 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.job.report;

import java.util.Base64;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.report.ReconciliationReportletConf;
import org.apache.syncope.common.lib.report.ReconciliationReportletConf.Feature;
import org.apache.syncope.common.lib.report.ReportletConf;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.AnyDAO;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
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.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.entity.Any;
import org.apache.syncope.core.persistence.api.entity.AnyType;
import org.apache.syncope.core.persistence.api.entity.AnyUtils;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
import org.apache.syncope.core.provisioning.api.Connector;
import org.apache.syncope.core.provisioning.api.ConnectorManager;
import org.apache.syncope.core.provisioning.api.MappingManager;
import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeBuilder;
import org.identityconnectors.framework.common.objects.ConnectorObject;
import org.identityconnectors.framework.common.objects.OperationalAttributes;
import org.identityconnectors.framework.common.objects.Uid;
import org.springframework.beans.factory.annotation.Autowired;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/**
 * Reportlet for extracting information for the current reconciliation status, e.g. the coherence between Syncope
 * information and mapped entities on external resources.
 */
@ReportletConfClass(ReconciliationReportletConf.class)
public class ReconciliationReportlet extends AbstractReportlet {

    private static final int PAGE_SIZE = 10;

    @Autowired
    private RealmDAO realmDAO;

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private GroupDAO groupDAO;

    @Autowired
    private AnyTypeDAO anyTypeDAO;

    @Autowired
    private AnySearchDAO searchDAO;

    @Autowired
    private MappingManager mappingManager;

    @Autowired
    private ConnectorManager connectorManager;

    @Autowired
    private AnyUtilsFactory anyUtilsFactory;

    @Autowired
    private SearchCondVisitor searchCondVisitor;

    private ReconciliationReportletConf conf;

    private static String getAnyElementName(final AnyTypeKind anyTypeKind) {
        String elementName;

        switch (anyTypeKind) {
            case USER:
                elementName = "user";
                break;

            case GROUP:
                elementName = "group";
                break;

            case ANY_OBJECT:
            default:
                elementName = "anyObject";
        }

        return elementName;
    }

    private void doExtract(
            final ContentHandler handler,
            final Any<?> any,
            final Set<Missing> missing,
            final Set<Misaligned> misaligned)
            throws SAXException {

        AttributesImpl atts = new AttributesImpl();

        for (Feature feature : conf.getFeatures()) {
            String type = null;
            String value = null;
            switch (feature) {
                case key:
                    type = ReportXMLConst.XSD_STRING;
                    value = any.getKey();
                    break;

                case username:
                    if (any instanceof User) {
                        type = ReportXMLConst.XSD_STRING;
                        value = User.class.cast(any).getUsername();
                    }
                    break;

                case groupName:
                    if (any instanceof Group) {
                        type = ReportXMLConst.XSD_STRING;
                        value = Group.class.cast(any).getName();
                    }
                    break;

                case status:
                    type = ReportXMLConst.XSD_STRING;
                    value = any.getStatus();
                    break;

                case creationDate:
                    type = ReportXMLConst.XSD_DATETIME;
                    value = any.getCreationDate() == null
                            ? StringUtils.EMPTY
                            : FormatUtils.format(any.getCreationDate());
                    break;

                case lastLoginDate:
                    if (any instanceof User) {
                        type = ReportXMLConst.XSD_DATETIME;
                        value = User.class.cast(any).getLastLoginDate() == null
                                ? StringUtils.EMPTY
                                : FormatUtils.format(User.class.cast(any).getLastLoginDate());
                    }
                    break;

                case changePwdDate:
                    if (any instanceof User) {
                        type = ReportXMLConst.XSD_DATETIME;
                        value = User.class.cast(any).getChangePwdDate() == null
                                ? StringUtils.EMPTY
                                : FormatUtils.format(User.class.cast(any).getChangePwdDate());
                    }
                    break;

                case passwordHistorySize:
                    if (any instanceof User) {
                        type = ReportXMLConst.XSD_INT;
                        value = String.valueOf(User.class.cast(any).getPasswordHistory().size());
                    }
                    break;

                case failedLoginCount:
                    if (any instanceof User) {
                        type = ReportXMLConst.XSD_INT;
                        value = String.valueOf(User.class.cast(any).getFailedLogins());
                    }
                    break;

                default:
            }

            if (type != null && value != null) {
                atts.addAttribute("", "", feature.name(), type, value);
            }
        }

        handler.startElement("", "", getAnyElementName(any.getType().getKind()), atts);

        for (Missing item : missing) {
            atts.clear();
            atts.addAttribute("", "", "resource", ReportXMLConst.XSD_STRING, item.getResource());
            atts.addAttribute("", "", "connObjectKeyValue", ReportXMLConst.XSD_STRING, item.getConnObjectKeyValue());

            handler.startElement("", "", "missing", atts);
            handler.endElement("", "", "missing");
        }
        for (Misaligned item : misaligned) {
            atts.clear();
            atts.addAttribute("", "", "resource", ReportXMLConst.XSD_STRING, item.getResource());
            atts.addAttribute("", "", "connObjectKeyValue", ReportXMLConst.XSD_STRING, item.getConnObjectKeyValue());
            atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, item.getName());

            handler.startElement("", "", "misaligned", atts);

            handler.startElement("", "", "onSyncope", null);
            if (item.getOnSyncope() != null) {
                for (Object value : item.getOnSyncope()) {
                    char[] asChars = value.toString().toCharArray();

                    handler.startElement("", "", "value", null);
                    handler.characters(asChars, 0, asChars.length);
                    handler.endElement("", "", "value");
                }
            }
            handler.endElement("", "", "onSyncope");

            handler.startElement("", "", "onResource", null);
            if (item.getOnResource() != null) {
                for (Object value : item.getOnResource()) {
                    char[] asChars = value.toString().toCharArray();

                    handler.startElement("", "", "value", null);
                    handler.characters(asChars, 0, asChars.length);
                    handler.endElement("", "", "value");
                }
            }
            handler.endElement("", "", "onResource");

            handler.endElement("", "", "misaligned");
        }

        handler.endElement("", "", getAnyElementName(any.getType().getKind()));
    }

    private static Set<Object> getValues(final Attribute attr) {
        Set<Object> values;
        if (attr.getValue() == null || attr.getValue().isEmpty()) {
            values = Set.of();
        } else if (attr.getValue().get(0) instanceof byte[]) {
            values = new HashSet<>(attr.getValue().size());
            attr.getValue().forEach(single -> values.add(Base64.getEncoder().encode((byte[]) single)));
        } else {
            values = new HashSet<>(attr.getValue());
        }

        return values;
    }

    private void doExtract(final ContentHandler handler, final List<? extends Any<?>> anys)
            throws SAXException, ReportException {

        final Set<Missing> missing = new HashSet<>();
        final Set<Misaligned> misaligned = new HashSet<>();

        for (Any<?> any : anys) {
            missing.clear();
            misaligned.clear();

            AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
            anyUtils.getAllResources(any).forEach(resource -> {
                Provision provision = resource.getProvision(any.getType()).orElse(null);
                Optional<? extends MappingItem> connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
                final String connObjectKeyValue = connObjectKeyItem.isPresent()
                        ? mappingManager.getConnObjectKeyValue(any, provision).get()
                        : StringUtils.EMPTY;
                if (provision != null && connObjectKeyItem.isPresent() && StringUtils.isNotBlank(connObjectKeyValue)) {
                    // 1. read from the underlying connector
                    Connector connector = connectorManager.getConnector(resource);
                    ConnectorObject connectorObject = connector.getObject(
                            provision.getObjectClass(),
                            AttributeBuilder.build(connObjectKeyItem.get().getExtAttrName(), connObjectKeyValue),
                            provision.isIgnoreCaseMatch(),
                            MappingUtils.buildOperationOptions(provision.getMapping().getItems().stream()));

                    if (connectorObject == null) {
                        // 2. not found on resource?
                        LOG.error("Object {} with class {} not found on resource {}",
                                connObjectKeyValue, provision.getObjectClass(), resource);

                        missing.add(new Missing(resource.getKey(), connObjectKeyValue));
                    } else {
                        // 3. found but misaligned?
                        Pair<String, Set<Attribute>> preparedAttrs =
                                mappingManager.prepareAttrsFromAny(any, null, false, null, provision);
                        preparedAttrs.getRight().add(AttributeBuilder.build(
                                Uid.NAME, preparedAttrs.getLeft()));
                        preparedAttrs.getRight().add(AttributeBuilder.build(
                                connObjectKeyItem.get().getExtAttrName(), preparedAttrs.getLeft()));

                        final Map<String, Set<Object>> syncopeAttrs = new HashMap<>();
                        preparedAttrs.getRight().forEach(attr -> syncopeAttrs.put(attr.getName(), getValues(attr)));

                        final Map<String, Set<Object>> resourceAttrs = new HashMap<>();
                        connectorObject.getAttributes().stream().
                                filter(attr -> (!OperationalAttributes.PASSWORD_NAME.equals(attr.getName())
                                && !OperationalAttributes.ENABLE_NAME.equals(attr.getName()))).
                                forEachOrdered(attr -> resourceAttrs.put(attr.getName(), getValues(attr)));

                        syncopeAttrs.keySet().stream().
                                filter(syncopeAttr -> !resourceAttrs.containsKey(syncopeAttr)).
                                forEach(name -> misaligned.add(new Misaligned(
                                resource.getKey(),
                                connObjectKeyValue,
                                name,
                                syncopeAttrs.get(name),
                                Set.of())));

                        resourceAttrs.forEach((key, values) -> {
                            if (syncopeAttrs.containsKey(key)) {
                                if (!Objects.equals(syncopeAttrs.get(key), values)) {
                                    misaligned.add(new Misaligned(
                                            resource.getKey(),
                                            connObjectKeyValue,
                                            key,
                                            syncopeAttrs.get(key),
                                            values));
                                }
                            } else {
                                misaligned.add(new Misaligned(
                                        resource.getKey(),
                                        connObjectKeyValue,
                                        key,
                                        Set.of(),
                                        values));
                            }
                        });
                    }
                }
            });

            if (!missing.isEmpty() || !misaligned.isEmpty()) {
                doExtract(handler, any, missing, misaligned);
            }
        }
    }

    @Override
    protected void doExtract(
            final ReportletConf conf,
            final ContentHandler handler,
            final AtomicReference<String> status)
            throws SAXException {

        if (conf instanceof ReconciliationReportletConf) {
            this.conf = ReconciliationReportletConf.class.cast(conf);
        } else {
            throw new ReportException(new IllegalArgumentException("Invalid configuration provided"));
        }

        AttributesImpl atts = new AttributesImpl();

        if (StringUtils.isBlank(this.conf.getUserMatchingCond())) {
            int total = userDAO.count();
            int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;

            status.set("Processing " + total + " users in " + pages + " pages");

            atts.addAttribute("", "", "total", ReportXMLConst.XSD_INT, String.valueOf(total));
            handler.startElement("", "", getAnyElementName(AnyTypeKind.USER) + 's', atts);

            for (int page = 1; page <= pages; page++) {
                status.set("Processing " + total + " users: page " + page + " of " + pages);

                doExtract(handler, userDAO.findAll(page, AnyDAO.DEFAULT_PAGE_SIZE));
            }
        } else {
            SearchCond cond = SearchCondConverter.convert(searchCondVisitor, this.conf.getUserMatchingCond());

            int total = searchDAO.count(
                    realmDAO.getRoot(),
                    true,
                    SyncopeConstants.FULL_ADMIN_REALMS,
                    cond,
                    AnyTypeKind.USER);
            int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;

            status.set("Processing " + total + " users in " + pages + " pages");

            atts.addAttribute("", "", "total", ReportXMLConst.XSD_INT, String.valueOf(total));
            handler.startElement("", "", getAnyElementName(AnyTypeKind.USER) + 's', atts);

            for (int page = 1; page <= pages; page++) {
                status.set("Processing " + total + " users: page " + page + " of " + pages);

                doExtract(handler, searchDAO.search(
                        realmDAO.getRoot(),
                        true,
                        SyncopeConstants.FULL_ADMIN_REALMS,
                        cond,
                        page,
                        PAGE_SIZE,
                        List.of(),
                        AnyTypeKind.USER));
            }
        }
        handler.endElement("", "", getAnyElementName(AnyTypeKind.USER) + 's');

        atts.clear();
        if (StringUtils.isBlank(this.conf.getGroupMatchingCond())) {
            int total = groupDAO.count();
            int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;

            status.set("Processing " + total + " groups in " + pages + " pages");

            atts.addAttribute("", "", "total", ReportXMLConst.XSD_INT, String.valueOf(total));
            handler.startElement("", "", getAnyElementName(AnyTypeKind.GROUP) + 's', atts);

            for (int page = 1; page <= pages; page++) {
                status.set("Processing " + total + " groups: page " + page + " of " + pages);

                doExtract(handler, groupDAO.findAll(page, AnyDAO.DEFAULT_PAGE_SIZE));
            }
        } else {
            SearchCond cond = SearchCondConverter.convert(searchCondVisitor, this.conf.getUserMatchingCond());

            int total = searchDAO.count(
                    realmDAO.getRoot(),
                    true,
                    SyncopeConstants.FULL_ADMIN_REALMS,
                    cond,
                    AnyTypeKind.GROUP);
            int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;

            status.set("Processing " + total + " groups in " + pages + " pages");

            atts.addAttribute("", "", "total", ReportXMLConst.XSD_INT, String.valueOf(total));
            handler.startElement("", "", getAnyElementName(AnyTypeKind.GROUP) + 's', atts);

            for (int page = 1; page <= pages; page++) {
                status.set("Processing " + total + " groups: page " + page + " of " + pages);

                doExtract(handler, searchDAO.search(
                        realmDAO.getRoot(),
                        true,
                        SyncopeConstants.FULL_ADMIN_REALMS,
                        cond,
                        page,
                        PAGE_SIZE,
                        List.of(),
                        AnyTypeKind.GROUP));
            }
        }
        handler.endElement("", "", getAnyElementName(AnyTypeKind.GROUP) + 's');

        for (AnyType anyType : anyTypeDAO.findAll()) {
            if (!anyType.equals(anyTypeDAO.findUser()) && !anyType.equals(anyTypeDAO.findGroup())) {
                AnyTypeCond anyTypeCond = new AnyTypeCond();
                anyTypeCond.setAnyTypeKey(anyType.getKey());
                SearchCond cond = StringUtils.isBlank(this.conf.getAnyObjectMatchingCond())
                        ? SearchCond.getLeaf(anyTypeCond)
                        : SearchCond.getAnd(
                                SearchCond.getLeaf(anyTypeCond),
                                SearchCondConverter.convert(searchCondVisitor, this.conf.getAnyObjectMatchingCond()));

                int total = searchDAO.count(
                        realmDAO.getRoot(),
                        true,
                        SyncopeConstants.FULL_ADMIN_REALMS,
                        cond,
                        AnyTypeKind.ANY_OBJECT);
                int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;

                status.set("Processing " + total + " any objects " + anyType.getKey() + " in " + pages + " pages");

                atts.clear();
                atts.addAttribute("", "", "type", ReportXMLConst.XSD_STRING, anyType.getKey());
                atts.addAttribute("", "", "total", ReportXMLConst.XSD_INT, String.valueOf(total));
                handler.startElement("", "", getAnyElementName(AnyTypeKind.ANY_OBJECT) + 's', atts);

                for (int page = 1; page <= pages; page++) {
                    status.set("Processing " + total + " any objects " + anyType.getKey()
                            + ": page " + page + " of " + pages);

                    doExtract(handler, searchDAO.search(
                            realmDAO.getRoot(),
                            true,
                            SyncopeConstants.FULL_ADMIN_REALMS,
                            cond,
                            page,
                            PAGE_SIZE,
                            List.of(),
                            AnyTypeKind.ANY_OBJECT));
                }

                handler.endElement("", "", getAnyElementName(AnyTypeKind.ANY_OBJECT) + 's');
            }
        }
    }

    private static class Missing {

        private final String resource;

        private final String connObjectKeyValue;

        Missing(final String resource, final String connObjectKeyValue) {
            this.resource = resource;
            this.connObjectKeyValue = connObjectKeyValue;
        }

        public String getResource() {
            return resource;
        }

        public String getConnObjectKeyValue() {
            return connObjectKeyValue;
        }

    }

    private static class Misaligned extends Missing {

        private final String name;

        private final Set<Object> onSyncope;

        private final Set<Object> onResource;

        Misaligned(
                final String resource,
                final String connObjectKeyValue,
                final String name,
                final Set<Object> onSyncope,
                final Set<Object> onResource) {

            super(resource, connObjectKeyValue);

            this.name = name;
            this.onSyncope = onSyncope;
            this.onResource = onResource;
        }

        public String getName() {
            return name;
        }

        public Set<Object> getOnSyncope() {
            return onSyncope;
        }

        public Set<Object> getOnResource() {
            return onResource;
        }

    }
}
