// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import semver from 'semver';

import type { ReadonlyDeep } from 'type-fest';

import { createLogger } from '../logging/log.std.ts';
import { isTestOrMockEnvironment } from '../environment.std.ts';
import { getValue, isEnabled } from '../RemoteConfig.dom.ts';
import { isAlpha, isBeta, isProduction, isStaging } from './version.std.ts';

import type { SemverKeyType, ConfigMapType } from '../RemoteConfig.dom.ts';

const log = createLogger('isFeatureEnabled');

export function isFeaturedEnabledSelector({
  betaKey,
  currentVersion,
  prodKey,
  remoteConfig,
}: {
  betaKey: SemverKeyType;
  currentVersion: string;
  prodKey: SemverKeyType;
  remoteConfig: ReadonlyDeep<ConfigMapType> | undefined;
}): boolean {
  return _isFeatureEnabledInner({
    betaValue: remoteConfig?.[betaKey]?.value,
    currentVersion,
    isInternalUser: remoteConfig?.['desktop.internalUser']?.enabled ?? false,
    prodValue: remoteConfig?.[prodKey]?.value,
  });
}

export function isFeaturedEnabledNoRedux({
  betaKey,
  prodKey,
}: {
  betaKey: SemverKeyType;
  prodKey: SemverKeyType;
}): boolean {
  return _isFeatureEnabledInner({
    betaValue: getValue(betaKey),
    currentVersion: window.getVersion(),
    isInternalUser: isEnabled('desktop.internalUser'),
    prodValue: getValue(prodKey),
  });
}

// Exported for testing
export function _isFeatureEnabledInner({
  betaValue,
  currentVersion,
  isInternalUser,
  prodValue,
  isTestEnvironment = isTestOrMockEnvironment,
}: {
  betaValue: string | undefined;
  currentVersion: string;
  isInternalUser: boolean;
  prodValue: string | undefined;
  isTestEnvironment?: () => boolean;
}): boolean {
  if (
    isInternalUser ||
    isAlpha(currentVersion) ||
    isStaging(currentVersion) ||
    isTestEnvironment()
  ) {
    return true;
  }

  if (!semver.parse(currentVersion)) {
    log.error(`currentVersion ${currentVersion} was invalid`);
    return false;
  }

  if (
    isBeta(currentVersion) &&
    betaValue &&
    semver.parse(betaValue) &&
    semver.gte(currentVersion, betaValue)
  ) {
    return true;
  }

  if (
    isProduction(currentVersion) &&
    prodValue &&
    semver.parse(prodValue) &&
    semver.gte(currentVersion, prodValue)
  ) {
    return true;
  }

  return false;
}
