package cloud.nstart.terravault.ordinis.domain.schemaworkflow;

/**
 * Schema workflow draft state machine.
 *
 * <p>Параллель к record-level {@link cloud.nstart.terravault.ordinis.domain.draft.DraftStatus},
 * но для schema-level changes (один draft = одно proposed schema state).
 *
 * <h3>Transitions</h3>
 * <pre>
 *   DRAFT             — maker создал, ещё не submit'нул
 *      → REVIEW_PENDING  (submit for review)
 *      → WITHDRAWN       (maker discards)
 *
 *   REVIEW_PENDING    — ждёт reviewer decision
 *      → APPROVED          (reviewer.decision=approve)
 *      → CHANGES_REQUESTED (reviewer.decision=request_changes)
 *      → REJECTED          (reviewer.decision=reject)
 *      → WITHDRAWN         (maker recall)
 *
 *   CHANGES_REQUESTED — maker должен доработать
 *      → REVIEW_PENDING  (re-submit)
 *      → WITHDRAWN       (maker abandons)
 *
 *   APPROVED          — готов к публикации
 *      → PUBLISHED       (publisher publishes, bump version)
 *      → WITHDRAWN       (maker withdraws even после approve, edge case)
 *
 *   PUBLISHED         — terminal (changes live)
 *   REJECTED          — terminal (kept for audit)
 *   WITHDRAWN         — terminal (kept for audit)
 * </pre>
 *
 * <p>Strings в БД lowercase (см. migration 0022 check constraint), JPA
 * {@code @Enumerated(EnumType.STRING)} mapping использует enum name — мы
 * храним в БД lowercase напрямую через
 * {@link com.fasterxml.jackson.annotation.JsonValue}-like преобразование
 * в Spring Data converter (см. также 0020 fix для record_drafts).
 */
public enum SchemaDraftStatus {
  DRAFT,
  REVIEW_PENDING,
  CHANGES_REQUESTED,
  APPROVED,
  REJECTED,
  PUBLISHED,
  WITHDRAWN;

  /** Terminal статусы — нельзя transition'нуть дальше. */
  public boolean isTerminal() {
    return this == PUBLISHED || this == REJECTED || this == WITHDRAWN;
  }

  /** Активный (non-terminal) — пользователь видит draft, может действовать. */
  public boolean isActive() {
    return !isTerminal();
  }

  /** Lowercase representation for DB column storage. */
  public String dbValue() {
    return name().toLowerCase();
  }

  /** Inverse of {@link #dbValue()} — parse from DB string. */
  public static SchemaDraftStatus fromDbValue(String s) {
    if (s == null) return null;
    return SchemaDraftStatus.valueOf(s.toUpperCase());
  }
}
