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

/**
 * Канал доставки уведомления.
 *
 * <p><b>Wire format — lowercase</b> ('email' / 'express' / 'telegram'). Такой
 * формат используется в:
 * <ul>
 *   <li>DB columns: {@code notification_log.channel}, {@code user_notification_prefs.channel}
 *       (см. CHECK constraint {@code notification_log_channel_check} в migration 0021)</li>
 *   <li>API JSON: {@code GET /api/v1/me/notifications}</li>
 *   <li>Helm config keys: {@code notifications.express.*}</li>
 *   <li>Metric labels: {@code nsi_notification_sent_total{channel="email"}}</li>
 * </ul>
 *
 * <p><b>NB:</b> {@code channel} column НЕ использует {@code @Enumerated(EnumType.STRING)} —
 * mapping ручной через {@link #wireName()}, чтобы DB хранила lowercase wire-format.
 * Это отличается от {@code notification_log.status}, который UPPERCASE
 * (carry-forward lesson из v1.1.0 P3 — Hibernate {@code @Enumerated(EnumType.STRING)}
 * пишет UPPERCASE, поэтому status CHECK в 0021 тоже UPPERCASE).
 *
 * <p>Persist: всегда {@link #wireName()} (lowercase). Read из DB: {@link #fromWireName(String)}.
 * Никогда не используй {@link Enum#name()} для DB/API — это вернёт UPPERCASE и
 * порушит CHECK constraint на insert.
 */
public enum ChannelKind {
  EMAIL("email"),
  EXPRESS("express"),
  TELEGRAM("telegram");

  private final String wireName;

  ChannelKind(String wireName) {
    this.wireName = wireName;
  }

  /**
   * Lower-case wire-format. Используется wherever DB / API / config / metrics
   * касаются channel identity. См. class-level Javadoc для полного списка
   * usage points.
   */
  public String wireName() {
    return wireName;
  }

  /** Парсинг из wire-format. Throws IllegalArgumentException на unknown value. */
  public static ChannelKind fromWireName(String wire) {
    if (wire == null) {
      throw new IllegalArgumentException("channel wire name is null");
    }
    for (ChannelKind k : values()) {
      if (k.wireName.equals(wire)) {
        return k;
      }
    }
    throw new IllegalArgumentException("unknown channel: " + wire);
  }
}
