/*
 * 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.fineract.cn.provisioner.internal.service;

import com.datastax.driver.core.ResultSet;
import com.datastax.driver.mapping.Mapper;
import com.datastax.driver.mapping.Result;
import org.apache.fineract.cn.provisioner.config.ProvisionerConstants;
import org.apache.fineract.cn.provisioner.internal.repository.ApplicationEntity;
import org.apache.fineract.cn.provisioner.internal.repository.TenantApplicationEntity;
import org.apache.fineract.cn.provisioner.internal.repository.TenantCassandraRepository;
import org.apache.fineract.cn.provisioner.internal.repository.TenantEntity;
import org.apache.fineract.cn.provisioner.internal.service.applications.AnubisInitializer;
import org.apache.fineract.cn.provisioner.internal.service.applications.IdentityServiceInitializer;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import org.apache.fineract.cn.anubis.api.v1.domain.ApplicationSignatureSet;
import org.apache.fineract.cn.anubis.config.TenantSignatureRepository;
import org.apache.fineract.cn.cassandra.core.CassandraSessionProvider;
import org.apache.fineract.cn.lang.AutoTenantContext;
import org.apache.fineract.cn.lang.ServiceException;
import org.apache.fineract.cn.lang.listening.EventExpectation;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

@Component
public class TenantApplicationService {

  private final CassandraSessionProvider cassandraSessionProvider;
  private final AnubisInitializer anubisInitializer;
  private final IdentityServiceInitializer identityServiceInitializer;
  private final TenantSignatureRepository tenantSignatureRepository;
  private final TenantCassandraRepository tenantCassandraRepository;
  private final Logger logger;

  @Autowired
  public TenantApplicationService(final CassandraSessionProvider cassandraSessionProvider,
                                  final AnubisInitializer anubisInitializer,
                                  final IdentityServiceInitializer identityServiceInitializer,
                                  @SuppressWarnings("SpringJavaAutowiringInspection") final TenantSignatureRepository tenantSignatureRepository,
                                  final TenantCassandraRepository tenantCassandraRepository,
                                  @Qualifier(ProvisionerConstants.LOGGER_NAME) final Logger logger) {
    super();
    this.cassandraSessionProvider = cassandraSessionProvider;
    this.anubisInitializer = anubisInitializer;
    this.identityServiceInitializer = identityServiceInitializer;
    this.tenantSignatureRepository = tenantSignatureRepository;
    this.tenantCassandraRepository = tenantCassandraRepository;
    this.logger = logger;
  }

  @Async
  public void assign(final @Nonnull TenantApplicationEntity tenantApplicationEntity, final @Nonnull Map<String, String> appNameToUriMap) {
    Assert.notNull(tenantApplicationEntity);
    Assert.notNull(appNameToUriMap);

    final TenantEntity tenantEntity = tenantCassandraRepository.get(tenantApplicationEntity.getTenantIdentifier())
            .orElseThrow(() -> ServiceException
                .notFound("Tenant {0} not found.", tenantApplicationEntity.getTenantIdentifier()));

    checkApplicationsExist(tenantApplicationEntity.getApplications());

    saveTenantApplicationAssignment(tenantApplicationEntity);

    final Set<ApplicationNameToUriPair> applicationNameToUriPairs =
            getApplicationNameToUriPairs(tenantApplicationEntity, appNameToUriMap);

    final Optional<ApplicationSignatureSet> latestIdentityManagerSignatureSet = getLatestIdentityManagerSignatureSet(tenantEntity);
    latestIdentityManagerSignatureSet.ifPresent(y -> {
              try {
                initializeSecurity(tenantEntity, y, applicationNameToUriPairs);
              } catch (final InterruptedException e) {
                logger.error("Because of interruption, started but didn't finish application assignment for {} in tenant {}.",
                        appNameToUriMap.keySet(), tenantApplicationEntity.getTenantIdentifier(), e);
              }
            });
    if (!latestIdentityManagerSignatureSet.isPresent()) {
      logger.warn("No identity manager signature is available, so security is not initialized for applications {}",
              appNameToUriMap.keySet());
    }
  }

  private void initializeSecurity(final TenantEntity tenantEntity,
                                  final ApplicationSignatureSet identityManagerSignatureSet,
                                  final Set<ApplicationNameToUriPair> applicationNameToUriPairs) throws InterruptedException {
    final String tenantIdentifier = tenantEntity.getIdentifier();
    final String identityManagerApplicationName = tenantEntity.getIdentityManagerApplicationName();
    final String identityManagerApplicationUri = tenantEntity.getIdentityManagerApplicationUri();

    //Permittable groups must be posted before resource initialization occurs because resource initialization
    //may request callback from another service. For example, Services X, Y, and Identity.
    // X.initializeResources -> Y.requestCallback at X.address
    // Y.requestCallback -> Identity.requestPermission to call X.address
    // Therefore Identity must know of the permittable group for X.address before X.initializeResources is called.
    final Stream<EventExpectation> eventExpectations = applicationNameToUriPairs.stream().flatMap(x ->
            identityServiceInitializer.postApplicationPermittableGroups(
                    tenantIdentifier,
                    identityManagerApplicationName,
                    identityManagerApplicationUri,
                    x.uri).stream());
    for (final EventExpectation eventExpectation : eventExpectations.collect(Collectors.toList())) {
      if (!eventExpectation.waitForOccurrence(5, TimeUnit.SECONDS)) {
        logger.warn("Expected action in identity didn't complete {}.", eventExpectation);
      }
    }


    applicationNameToUriPairs.forEach(x -> {
      final ApplicationSignatureSet applicationSignatureSet = anubisInitializer.createSignatureSet(tenantIdentifier, x.name, x.uri, identityManagerSignatureSet.getTimestamp(), identityManagerSignatureSet.getIdentityManagerSignature());

      identityServiceInitializer.postApplicationDetails(
              tenantIdentifier,
              identityManagerApplicationName,
              identityManagerApplicationUri,
              x.name,
              x.uri,
              applicationSignatureSet);

      //InitializeResources on the service being added should occur last, for two reasons:
      // 1.) When the initialization event is put on the queue for this app/tenant combo, the app is fully ready for business.
      // 2.) If the app depends on the provisioning of identitypermissions in its initialization, those resources will be there.
      anubisInitializer.initializeResources(tenantIdentifier, x.name, x.uri);
    });
  }

  private void saveTenantApplicationAssignment(final @Nonnull TenantApplicationEntity tenantApplicationEntity) {
    final Mapper<TenantApplicationEntity> tenantApplicationEntityMapper =
            this.cassandraSessionProvider.getAdminSessionMappingManager().mapper(TenantApplicationEntity.class);

    tenantApplicationEntityMapper.save(tenantApplicationEntity);
  }

  private Set<ApplicationNameToUriPair> getApplicationNameToUriPairs(
          final @Nonnull TenantApplicationEntity tenantApplicationEntity,
          final @Nonnull Map<String, String> appNameToUriMap) {
    return tenantApplicationEntity.getApplications().stream()
            .map(x -> new TenantApplicationService.ApplicationNameToUriPair(x, appNameToUriMap.get(x)))
            .collect(Collectors.toSet());
  }

  private static class ApplicationNameToUriPair
  {
    String name;
    String uri;

    ApplicationNameToUriPair(String name, String uri) {
      this.name = name;
      this.uri = uri;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      ApplicationNameToUriPair that = (ApplicationNameToUriPair) o;
      return Objects.equals(name, that.name) &&
              Objects.equals(uri, that.uri);
    }

    @Override
    public int hashCode() {
      return Objects.hash(name, uri);
    }
  }

  private Optional<ApplicationSignatureSet> getLatestIdentityManagerSignatureSet(final @Nonnull TenantEntity tenantEntity) {
    try (final AutoTenantContext ignored = new AutoTenantContext(tenantEntity.getIdentifier())) {
      return tenantSignatureRepository.getLatestSignatureSet();
    }
  }

  public TenantApplicationEntity find(final String tenantIdentifier) {
    checkTenant(tenantIdentifier);

    final Mapper<TenantApplicationEntity> tenantApplicationEntityMapper =
        this.cassandraSessionProvider.getAdminSessionMappingManager().mapper(TenantApplicationEntity.class);

    return tenantApplicationEntityMapper.get(tenantIdentifier);
  }

  void deleteTenant(final String tenantIdentifier) {
    final Mapper<TenantApplicationEntity> tenantApplicationEntityMapper =
        this.cassandraSessionProvider.getAdminSessionMappingManager().mapper(TenantApplicationEntity.class);

    tenantApplicationEntityMapper.delete(tenantIdentifier);
  }

  void removeApplication(final String name) {
    final ResultSet tenantApplicationResultSet =
        this.cassandraSessionProvider.getAdminSession().execute("SELECT * FROM tenant_applications");

    if (tenantApplicationResultSet != null) {
      final Mapper<TenantApplicationEntity> tenantApplicationEntityMapper =
          this.cassandraSessionProvider.getAdminSessionMappingManager().mapper(TenantApplicationEntity.class);

      final Result<TenantApplicationEntity> mappedTenantApplications = tenantApplicationEntityMapper.map(tenantApplicationResultSet);

      for (TenantApplicationEntity tenantApplicationEntity : mappedTenantApplications) {
        if (tenantApplicationEntity.getApplications().contains(name)) {
          tenantApplicationEntity.getApplications().remove(name);
          tenantApplicationEntityMapper.save(tenantApplicationEntity);
        }
      }
    }
  }

  private void checkApplicationsExist(final Set<String> applications) {
    final Mapper<ApplicationEntity> applicationEntityMapper =
            this.cassandraSessionProvider.getAdminSessionMappingManager().mapper(ApplicationEntity.class);

    for (final String name : applications) {
      if (applicationEntityMapper.get(name) == null) {
        throw ServiceException.badRequest("Application {0} not found!", name);
      }
    }
  }

  private void checkTenant(final @Nonnull String tenantIdentifier) {
    final Optional<TenantEntity> tenantEntity = tenantCassandraRepository.get(tenantIdentifier);
    tenantEntity.orElseThrow(() -> ServiceException.notFound("Tenant {0} not found.", tenantIdentifier));
  }
}
