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

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.persistence.DiscriminatorValue;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.to.PropagationTaskTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.ExecStatus;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.core.persistence.api.dao.RemediationDAO;
import org.apache.syncope.core.persistence.api.dao.TaskDAO;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.entity.Entity;
import org.apache.syncope.core.persistence.api.entity.Implementation;
import org.apache.syncope.core.persistence.api.entity.Notification;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
import org.apache.syncope.core.persistence.api.entity.task.PullTask;
import org.apache.syncope.core.persistence.api.entity.task.PushTask;
import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
import org.apache.syncope.core.persistence.api.entity.task.Task;
import org.apache.syncope.core.persistence.jpa.entity.task.JPANotificationTask;
import org.apache.syncope.core.persistence.jpa.entity.task.JPAPropagationTask;
import org.apache.syncope.core.persistence.jpa.entity.task.JPAPushTask;
import org.apache.syncope.core.persistence.jpa.entity.task.JPASchedTask;
import org.apache.syncope.core.persistence.jpa.entity.task.JPAPullTask;
import org.apache.syncope.core.persistence.jpa.entity.task.AbstractTask;
import org.apache.syncope.core.persistence.jpa.entity.task.JPATaskExec;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;

public class JPATaskDAO extends AbstractDAO<Task> implements TaskDAO {

    protected static String getEntityTableName(final TaskType type) {
        String result = null;

        switch (type) {
            case NOTIFICATION:
                result = JPANotificationTask.class.getAnnotation(DiscriminatorValue.class).value();
                break;

            case PROPAGATION:
                result = JPAPropagationTask.class.getAnnotation(DiscriminatorValue.class).value();
                break;

            case PUSH:
                result = JPAPushTask.class.getAnnotation(DiscriminatorValue.class).value();
                break;

            case SCHEDULED:
                result = JPASchedTask.class.getAnnotation(DiscriminatorValue.class).value();
                break;

            case PULL:
                result = JPAPullTask.class.getAnnotation(DiscriminatorValue.class).value();
                break;

            default:
        }

        return result;
    }

    protected final RemediationDAO remediationDAO;

    public JPATaskDAO(final RemediationDAO remediationDAO) {
        this.remediationDAO = remediationDAO;
    }

    @Override
    public Class<? extends Task> getEntityReference(final TaskType type) {
        Class<? extends Task> result = null;

        switch (type) {
            case NOTIFICATION:
                result = JPANotificationTask.class;
                break;

            case PROPAGATION:
                result = JPAPropagationTask.class;
                break;

            case PUSH:
                result = JPAPushTask.class;
                break;

            case SCHEDULED:
                result = JPASchedTask.class;
                break;

            case PULL:
                result = JPAPullTask.class;
                break;

            default:
        }

        return result;
    }

    @Transactional(readOnly = true)
    @SuppressWarnings("unchecked")
    @Override
    public <T extends Task> T find(final String key) {
        return (T) entityManager().find(AbstractTask.class, key);
    }

    @Override
    public List<SchedTask> findByDelegate(final Implementation delegate) {
        TypedQuery<SchedTask> query = entityManager().createQuery(
                "SELECT e FROM " + JPASchedTask.class.getSimpleName()
                + " e WHERE e.jobDelegate=:delegate", SchedTask.class);
        query.setParameter("delegate", delegate);

        return query.getResultList();
    }

    @Override
    public List<PullTask> findByReconFilterBuilder(final Implementation reconFilterBuilder) {
        TypedQuery<PullTask> query = entityManager().createQuery(
                "SELECT e FROM " + JPAPullTask.class.getSimpleName()
                + " e WHERE e.reconFilterBuilder=:reconFilterBuilder", PullTask.class);
        query.setParameter("reconFilterBuilder", reconFilterBuilder);

        return query.getResultList();
    }

    @Override
    public List<PullTask> findByPullActions(final Implementation pullActions) {
        TypedQuery<PullTask> query = entityManager().createQuery(
                "SELECT e FROM " + JPAPullTask.class.getSimpleName() + " e "
                + "WHERE :pullActions MEMBER OF e.actions", PullTask.class);
        query.setParameter("pullActions", pullActions);

        return query.getResultList();
    }

    @Override
    public List<PushTask> findByPushActions(final Implementation pushActions) {
        TypedQuery<PushTask> query = entityManager().createQuery(
                "SELECT e FROM " + JPAPushTask.class.getSimpleName() + " e "
                + "WHERE :pushActions MEMBER OF e.actions", PushTask.class);
        query.setParameter("pushActions", pushActions);

        return query.getResultList();
    }

    protected final <T extends Task> StringBuilder buildFindAllQueryJPA(final TaskType type) {
        StringBuilder builder = new StringBuilder("SELECT t FROM ").
                append(getEntityReference(type).getSimpleName()).
                append(" t WHERE ");
        if (type == TaskType.SCHEDULED) {
            builder.append("t.id NOT IN (SELECT t.id FROM ").
                    append(JPAPushTask.class.getSimpleName()).append(" t) ").
                    append("AND ").
                    append("t.id NOT IN (SELECT t.id FROM ").
                    append(JPAPullTask.class.getSimpleName()).append(" t)");
        } else {
            builder.append("1=1");
        }

        return builder.append(' ');
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T extends Task> List<T> findToExec(final TaskType type) {
        StringBuilder queryString = buildFindAllQueryJPA(type).append("AND ");

        if (type == TaskType.NOTIFICATION) {
            queryString.append("t.executed = false ");
        } else {
            queryString.append("t.executions IS EMPTY ");
        }
        queryString.append("ORDER BY t.id DESC");

        Query query = entityManager().createQuery(queryString.toString());
        return query.getResultList();
    }

    @Transactional(readOnly = true)
    @Override
    public <T extends Task> List<T> findAll(final TaskType type) {
        return findAll(type, null, null, null, null, -1, -1, List.of());
    }

    protected StringBuilder buildFindAllQuery(
            final TaskType type,
            final ExternalResource resource,
            final Notification notification,
            final AnyTypeKind anyTypeKind,
            final String entityKey,
            final boolean orderByTaskExecInfo,
            final List<Object> queryParameters) {

        if (resource != null
                && type != TaskType.PROPAGATION && type != TaskType.PUSH && type != TaskType.PULL) {

            throw new IllegalArgumentException(type + " is not related to " + ExternalResource.class.getSimpleName());
        }

        if ((anyTypeKind != null || entityKey != null)
                && type != TaskType.PROPAGATION && type != TaskType.NOTIFICATION) {

            throw new IllegalArgumentException(type + " is not related to users, groups or any objects");
        }

        if (notification != null && type != TaskType.NOTIFICATION) {
            throw new IllegalArgumentException(type + " is not related to notifications");
        }

        StringBuilder queryString = new StringBuilder("SELECT ").append(AbstractTask.TABLE).append(".*");

        if (orderByTaskExecInfo) {
            queryString.append(',').append(JPATaskExec.TABLE).append(".startDate AS startDate").
                    append(',').append(JPATaskExec.TABLE).append(".endDate AS endDate").
                    append(',').append(JPATaskExec.TABLE).append(".status AS status").
                    append(" FROM ").append(AbstractTask.TABLE).
                    append(',').append(JPATaskExec.TABLE).append(',').append("(SELECT ").
                    append(JPATaskExec.TABLE).append(".task_id, ").
                    append("MAX(").append(JPATaskExec.TABLE).append(".startDate) AS startDate").
                    append(" FROM ").append(JPATaskExec.TABLE).
                    append(" GROUP BY ").append(JPATaskExec.TABLE).append(".task_id) GRP").
                    append(" WHERE ").
                    append(AbstractTask.TABLE).append(".id=").append(JPATaskExec.TABLE).append(".task_id").
                    append(" AND ").append(AbstractTask.TABLE).append(".id=").append("GRP.task_id").
                    append(" AND ").append(JPATaskExec.TABLE).append(".startDate=").append("GRP.startDate").
                    append(" AND ").append(AbstractTask.TABLE).append(".DTYPE = ?1");
        } else {
            queryString.append(", null AS startDate, null AS endDate, null AS status FROM ").append(AbstractTask.TABLE).
                    append(" WHERE ").append(AbstractTask.TABLE).append(".DTYPE = ?1");
        }

        queryParameters.add(getEntityTableName(type));
        if (type == TaskType.SCHEDULED) {
            queryString.append(" AND ").
                    append(AbstractTask.TABLE).
                    append(".id NOT IN (SELECT ").append(AbstractTask.TABLE).append(".id FROM ").
                    append(AbstractTask.TABLE).append(" WHERE ").
                    append(AbstractTask.TABLE).append(".DTYPE = ?2)").
                    append(" AND ").
                    append(AbstractTask.TABLE).
                    append(".id NOT IN (SELECT id FROM ").
                    append(AbstractTask.TABLE).append(" WHERE ").
                    append(AbstractTask.TABLE).append(".DTYPE = ?3)");

            queryParameters.add(JPAPushTask.class.getAnnotation(DiscriminatorValue.class).value());
            queryParameters.add(JPAPullTask.class.getAnnotation(DiscriminatorValue.class).value());
        }
        queryString.append(' ');

        if (resource != null) {
            queryParameters.add(resource.getKey());

            queryString.append(" AND ").
                    append(AbstractTask.TABLE).
                    append(".resource_id=?").append(queryParameters.size());
        }
        if (notification != null) {
            queryParameters.add(notification.getKey());

            queryString.append(" AND ").
                    append(AbstractTask.TABLE).
                    append(".notification_id=?").append(queryParameters.size());
        }
        if (anyTypeKind != null && entityKey != null) {
            queryParameters.add(anyTypeKind.name());
            queryParameters.add(entityKey);

            queryString.append(" AND ").
                    append(AbstractTask.TABLE).
                    append(".anyTypeKind=?").append(queryParameters.size() - 1).
                    append(" AND ").
                    append(AbstractTask.TABLE).
                    append(".entityKey=?").append(queryParameters.size());
        }

        return queryString;
    }

    protected String toOrderByStatement(
            final Class<? extends Task> beanClass,
            final List<OrderByClause> orderByClauses) {

        StringBuilder statement = new StringBuilder();

        statement.append(" ORDER BY ");

        StringBuilder subStatement = new StringBuilder();
        orderByClauses.forEach(clause -> {
            String field = clause.getField().trim();
            switch (field) {
                case "latestExecStatus":
                    field = "status";
                    break;

                case "start":
                    field = "startDate";
                    break;

                case "end":
                    field = "endDate";
                    break;

                default:
                    Field beanField = ReflectionUtils.findField(beanClass, field);
                    if (beanField != null
                            && (beanField.getAnnotation(ManyToOne.class) != null
                            || beanField.getAnnotation(OneToMany.class) != null)) {
                        field += "_id";
                    }
            }

            subStatement.append(field).append(' ').append(clause.getDirection().name()).append(',');
        });

        if (subStatement.length() == 0) {
            statement.append("id DESC");
        } else {
            subStatement.deleteCharAt(subStatement.length() - 1);
            statement.append(subStatement);
        }

        return statement.toString();
    }

    @Override
    public <T extends Task> List<T> findAll(
            final TaskType type,
            final ExternalResource resource,
            final Notification notification,
            final AnyTypeKind anyTypeKind,
            final String entityKey,
            final int page,
            final int itemsPerPage,
            final List<OrderByClause> orderByClauses) {

        List<Object> queryParameters = new ArrayList<>();

        boolean orderByTaskExecInfo = orderByClauses.stream().
                anyMatch(clause -> clause.getField().equals("start")
                || clause.getField().equals("end")
                || clause.getField().equals("latestExecStatus")
                || clause.getField().equals("status"));

        StringBuilder queryString = buildFindAllQuery(
                type,
                resource,
                notification,
                anyTypeKind,
                entityKey,
                orderByTaskExecInfo,
                queryParameters);

        if (orderByTaskExecInfo) {
            // UNION with tasks without executions...
            queryString.insert(0, "SELECT T.id FROM ((").append(") UNION ALL (").
                    append(buildFindAllQuery(
                            type,
                            resource,
                            notification,
                            anyTypeKind,
                            entityKey,
                            false,
                            queryParameters)).
                    append(" AND id NOT IN ").
                    append("(SELECT task_id AS id FROM ").append(JPATaskExec.TABLE).append(')').
                    append(")) T");
        } else {
            queryString.insert(0, "SELECT T.id FROM (").append(") T");
        }

        queryString.append(toOrderByStatement(getEntityReference(type), orderByClauses));

        Query query = entityManager().createNativeQuery(queryString.toString());

        for (int i = 1; i <= queryParameters.size(); i++) {
            query.setParameter(i, queryParameters.get(i - 1));
        }

        query.setFirstResult(itemsPerPage * (page <= 0 ? 0 : page - 1));

        if (itemsPerPage > 0) {
            query.setMaxResults(itemsPerPage);
        }

        List<T> result = new ArrayList<>();

        @SuppressWarnings("unchecked")
        List<Object> raw = query.getResultList();
        raw.stream().map(key -> key instanceof Object[]
                ? (String) ((Object[]) key)[0]
                : ((String) key)).forEach(key -> {

            T task = find(key);
            if (task == null) {
                LOG.error("Could not find task with key {}, even if returned by native query", key);
            } else if (!result.contains(task)) {
                result.add(task);
            }
        });

        return result;
    }

    @Override
    public int count(
            final TaskType type,
            final ExternalResource resource,
            final Notification notification,
            final AnyTypeKind anyTypeKind,
            final String entityKey) {

        List<Object> queryParameters = new ArrayList<>();

        StringBuilder queryString =
                buildFindAllQuery(type, resource, notification, anyTypeKind, entityKey, false, queryParameters);

        Query query = entityManager().createNativeQuery(StringUtils.replaceOnce(
                queryString.toString(),
                "SELECT " + AbstractTask.TABLE + ".*, null AS startDate, null AS endDate, null AS status",
                "SELECT COUNT(" + AbstractTask.TABLE + ".id)"));

        for (int i = 1; i <= queryParameters.size(); i++) {
            query.setParameter(i, queryParameters.get(i - 1));
        }

        return ((Number) query.getSingleResult()).intValue();
    }

    @Transactional(rollbackFor = { Throwable.class })
    @Override
    public <T extends Task> T save(final T task) {
        return entityManager().merge(task);
    }

    @Override
    public void delete(final String id) {
        Task task = find(id);
        if (task == null) {
            return;
        }

        delete(task);
    }

    @Override
    public void delete(final Task task) {
        if (task instanceof PullTask) {
            remediationDAO.findByPullTask((PullTask) task).forEach(remediation -> remediation.setPullTask(null));
        }

        entityManager().remove(task);
    }

    @Override
    public void deleteAll(final ExternalResource resource, final TaskType type) {
        findAll(type, resource, null, null, null, -1, -1, List.of()).
                stream().map(Entity::getKey).forEach(this::delete);
    }

    @Override
    public List<PropagationTaskTO> purgePropagations(final Date since, final List<ExecStatus> statuses) {
        StringBuilder queryString = new StringBuilder("SELECT t.task_id "
                + "FROM TaskExec t INNER JOIN Task z ON t.task_id=z.id AND z.dtype='PropagationTask' "
                + "WHERE t.enddate=(SELECT MAX(e.enddate) FROM TaskExec e WHERE e.task_id=t.task_id) ");

        List<Object> queryParameters = new ArrayList<>();
        if (since != null) {
            queryParameters.add(since);
            queryString.append("AND t.enddate <= ?").append(queryParameters.size()).append(' ');
        }
        if (!CollectionUtils.isEmpty(statuses)) {
            queryString.append("AND (").
                    append(statuses.stream().map(status -> {
                        queryParameters.add(status.name());
                        return "t.status = ?" + queryParameters.size();
                    }).collect(Collectors.joining(" OR "))).
                    append(")");
        }

        Query query = entityManager().createNativeQuery(queryString.toString());
        for (int i = 1; i <= queryParameters.size(); i++) {
            query.setParameter(i, queryParameters.get(i - 1));
        }

        @SuppressWarnings("unchecked")
        List<Object> raw = query.getResultList();

        List<PropagationTaskTO> purged = new ArrayList<>();
        raw.stream().map(Object::toString).distinct().forEach(key -> {
            PropagationTask task = find(key);
            if (task != null) {
                PropagationTaskTO taskTO = new PropagationTaskTO();

                taskTO.setOperation(task.getOperation());
                taskTO.setConnObjectKey(task.getConnObjectKey());
                taskTO.setOldConnObjectKey(task.getOldConnObjectKey());
                taskTO.setAttributes(task.getSerializedAttributes());
                taskTO.setResource(task.getResource().getKey());
                taskTO.setObjectClassName(task.getObjectClassName());
                taskTO.setAnyTypeKind(task.getAnyTypeKind());
                taskTO.setAnyType(task.getAnyType());
                taskTO.setEntityKey(task.getEntityKey());

                purged.add(taskTO);

                delete(task);
            }
        });

        return purged;
    }
}
