// Copyright (C) 2024 The Android Open Source Project
//
// Licensed 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.

import com.google.common.cache.*
import com.google.common.flogger.*
import com.google.gerrit.common.*
import com.google.gerrit.entities.*
import com.google.gerrit.extensions.annotations.*
import com.google.gerrit.extensions.events.*
import com.google.gerrit.extensions.registration.*
import com.google.gerrit.metrics.*
import com.google.gerrit.lifecycle.*
import com.google.gerrit.server.*
import com.google.gerrit.server.account.*
import com.google.gerrit.server.cache.*
import com.google.gerrit.server.config.*
import com.google.gerrit.server.project.*
import com.google.inject.*
import com.google.inject.name.*

import java.time.*
import java.util.function.*
import java.util.stream.Collectors

import static java.util.concurrent.TimeUnit.*

@Singleton
class ActiveUsersMetric {

  static final NAME = "active_users"
  static final DESCRIPTION = "Number of active users"

  @Inject
  public ActiveUsersMetric(MetricMaker metrics, @Named(TrackActiveUsersCache.NAME) Cache<Integer, Long> trackActiveUsersCache){
    metrics.newCallbackMetric(
      NAME,
      Long.class,
      new Description(DESCRIPTION).setGauge().setUnit("users"),
      { -> trackActiveUsersCache.size() }
    );
  }
}

class TrackActiveUsersCache extends CacheModule {
  static final NAME = "users_cache"
  static final DEFAULT_CACHE_TTL = Duration.ofDays(90)
  static final MAX_SIZE = 300_000

  @Override
  protected void configure() {
    persist(NAME, Integer, Long)
        .diskLimit(MAX_SIZE)
        .maximumWeight(MAX_SIZE)
        .expireAfterWrite(DEFAULT_CACHE_TTL)
  }
}

@Singleton
class TrackingGroupBackend implements GroupBackend {
  @Inject
  @Named(TrackActiveUsersCache.NAME)
  Cache<Integer, Long> trackActiveUsersCache

  @Override
  boolean handles(AccountGroup.UUID uuid) {
    return true
  }

  @Override
  GroupDescription.Basic get(AccountGroup.UUID uuid) {
    return null
  }

  @Override
  Collection<GroupReference> suggest(String name, @Nullable ProjectState project) {
    return Collections.emptyList()
  }

  @Override
  GroupMembership membershipsOf(CurrentUser user) {
    if (user.identifiedUser) {
      def accountId = user.accountId.get()
      def currentMinutes = MILLISECONDS.toMinutes(System.currentTimeMillis())
      if (trackActiveUsersCache.getIfPresent(accountId) != currentMinutes) {
        trackActiveUsersCache.put(accountId, currentMinutes)
      }
    }
    return GroupMembership.EMPTY
  }

  @Override
  boolean isVisibleToAll(AccountGroup.UUID uuid) {
    return false
  }
}
class AutoDisableInactiveUsersConfig {
  final Set<Account.Id> ignoreAccountIds

  private final PluginConfig config

  @Inject
  AutoDisableInactiveUsersConfig(
      PluginConfigFactory configFactory,
      @PluginName String pluginName
  ) {
    config = configFactory.getFromGerritConfig(pluginName)

    ignoreAccountIds = ignoreAccountIdsFromConfig("ignoreAccountId")
  }

  private Set<Account.Id> ignoreAccountIdsFromConfig(String name) {
    def strings = config.getStringList(name) as Set
    strings.stream()
        .map(Account.Id.&tryParse)
        .filter { it.isPresent() }
        .map { it.get() }
        .collect(Collectors.toSet())
  }
}

class AutoDisableInactiveUsersEvictionListener implements CacheRemovalListener<Integer, Long> {
  static final FluentLogger logger = FluentLogger.forEnclosingClass()

  private final String pluginName
  private final String fullCacheName
  private final Cache<Integer, Long> trackActiveUsersCache
  private final Provider<AccountsUpdate> accountsUpdate
  private final AutoDisableInactiveUsersConfig autoDisableConfig

  @Inject
  AutoDisableInactiveUsersEvictionListener(
      @PluginName String pluginName,
      @ServerInitiated Provider<AccountsUpdate> accountsUpdate,
      @Named(TrackActiveUsersCache.NAME) Cache<Integer, Long> trackActiveUsersCache,
      AutoDisableInactiveUsersConfig autoDisableConfig
  ) {
    this.pluginName = pluginName
    this.accountsUpdate = accountsUpdate
    this.autoDisableConfig = autoDisableConfig
    this.trackActiveUsersCache = trackActiveUsersCache
    fullCacheName = "${pluginName}.${TrackActiveUsersCache.NAME}"
  }

  @Override
  void onRemoval(String pluginName, String cacheName, RemovalNotification<Integer, Long> notification) {
    if (fullCacheName != cacheName) {
      return
    }

    if (notification.cause == RemovalCause.EXPIRED) {
      disableAccount(Account.id(notification.key))
    } else if (notification.cause == RemovalCause.EXPLICIT) {
      logger.atWarning().log(
          "cache %s do not support eviction, entry for user %d will be added back", fullCacheName, notification.key)
      trackActiveUsersCache.put(notification.key, notification.value)
    }
  }

  private void disableAccount(Account.Id accountId) {
    if (autoDisableConfig.ignoreAccountIds.contains(accountId)) {
      return
    }

    logger.atInfo().log("Automatically disabling user id: %d", accountId.get())
    accountsUpdate.get().update(
        """Automatically disabling after inactivity

Disabled by ${pluginName}""",
        accountId,
        new Consumer<AccountDelta.Builder>() {
          @Override
          void accept(AccountDelta.Builder builder) {
            builder.setActive(false)
          }
        })
  }
}

@Singleton
class AutoDisableInactiveUsersListener implements LifecycleListener {
  static final FluentLogger logger = FluentLogger.forEnclosingClass()

  @Inject
  Accounts accounts

  @Inject
  ServiceUserClassifier serviceUserClassifier

  @Inject
  @Named(TrackActiveUsersCache.NAME)
  Cache<Integer, Long> trackActiveUsersCache

  @Override
  void start() {
    def currentMinutes = MILLISECONDS.toMinutes(System.currentTimeMillis())
    accounts.all()
        .findAll {
          it.account().isActive() && !serviceUserClassifier.isServiceUser(it.account().id()) && !trackActiveUsersCache.getIfPresent(it.account().id().get())
        }
        .each { trackActiveUsersCache.put(it.account().id().get(), currentMinutes) }
  }

  @Override
  void stop() {
    // no-op
  }
}

class TrackAndDisableInactiveUsersModule extends LifecycleModule {
  @Override
  void configure() {
    install(new TrackActiveUsersCache())
    bind(ActiveUsersMetric.class).asEagerSingleton()
    listener().to(AutoDisableInactiveUsersListener)
    DynamicSet.bind(binder(), CacheRemovalListener).to(AutoDisableInactiveUsersEvictionListener)

    DynamicSet.bind(binder(), GroupBackend).to(TrackingGroupBackend)
  }
}

modules = [TrackAndDisableInactiveUsersModule]
