package cloud.nstart.terravault.ordinis.notifications.dispatcher;

import cloud.nstart.terravault.ordinis.domain.notification.UserNotificationPref;
import cloud.nstart.terravault.ordinis.domain.notification.UserNotificationPrefRepository;
import cloud.nstart.terravault.ordinis.notifications.channel.ChannelKind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * Per-recipient channel preferences gate — checks user_notification_prefs row
 * before dispatcher actually sends. Phase B (`/me/notifications/preferences` UI).
 *
 * <p>Default semantics when row is MISSING (user never visited preferences page):
 * <ul>
 *   <li>{@link ChannelKind#EMAIL} — ON (matches Phase A default-on behavior).</li>
 *   <li>{@link ChannelKind#EXPRESS} / {@link ChannelKind#TELEGRAM} — OFF (require
 *       explicit opt-in; channels also not implemented yet on backend).</li>
 * </ul>
 *
 * <p>Reviewer-pool pseudo-user ({@code userId="reviewer-pool"}) bypasses gate —
 * pool is a shared inbox, individual prefs don't apply. Always considered ON.
 *
 * <p>{@code @ConditionalOnProperty} mirrors {@link NotificationsDispatcher} —
 * bean не register'ится без {@code ordinis.notifications.enabled=true}.
 */
@Component
@ConditionalOnProperty(name = "ordinis.notifications.enabled", havingValue = "true", matchIfMissing = false)
public class UserPreferencesGate {

  private static final Logger log = LoggerFactory.getLogger(UserPreferencesGate.class);

  /** Pseudo userId used for the reviewer-pool shared inbox. Never has prefs. */
  public static final String REVIEWER_POOL_USER_ID = "reviewer-pool";

  private final UserNotificationPrefRepository repo;

  public UserPreferencesGate(UserNotificationPrefRepository repo) {
    this.repo = repo;
  }

  /**
   * @return true если recipient should receive notification on this channel.
   *         Considers default-on policy (EMAIL) и default-off (EXPRESS/TELEGRAM).
   */
  public boolean allows(String userId, ChannelKind channel) {
    if (userId == null || userId.isBlank()) {
      return defaultFor(channel);
    }
    if (REVIEWER_POOL_USER_ID.equals(userId)) {
      // Pool is a shared inbox — always ON, prefs don't apply.
      return true;
    }
    Optional<UserNotificationPref> row = repo.findByIdUserIdAndIdChannel(userId, channel.wireName());
    if (row.isEmpty()) {
      boolean defaultOn = defaultFor(channel);
      log.trace("No prefs row for user={} channel={}, defaulting to {}",
          userId, channel.wireName(), defaultOn);
      return defaultOn;
    }
    return row.get().isEnabled();
  }

  /**
   * Default policy when no row exists. EMAIL = ON (preserves Phase A behavior
   * где users получали emails by default). Others = OFF (require opt-in).
   */
  private boolean defaultFor(ChannelKind channel) {
    return channel == ChannelKind.EMAIL;
  }
}
