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

import com.fasterxml.jackson.databind.JsonNode;
import io.hypersistence.utils.hibernate.type.json.JsonType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Version;
import org.hibernate.annotations.Type;
import org.locationtech.jts.geom.Geometry;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.OffsetDateTime;
import java.util.UUID;

/**
 * Approval workflow draft (v2 epic). Sits в DRAFT layer — не виден existing
 * read endpoints (`/dictionaries/{name}/records`) до approve'а. Approved
 * drafts COPY'ятся в {@link cloud.nstart.terravault.ordinis.domain.record.DictionaryRecord}
 * + delete'ятся (либо kept для status=approved log; design TBD Phase 1).
 *
 * <p>Constraints в БД (см. Liquibase 0019):
 * <ul>
 *   <li>{@code record_drafts_status_check} — pending/approved/rejected/withdrawn.</li>
 *   <li>{@code record_drafts_operation_check} — CREATE/UPDATE/CLOSE.</li>
 *   <li>{@code record_drafts_no_self_approve} — maker_id != reviewer_id.</li>
 *   <li>{@code record_drafts_one_pending_per_key} — EXCLUDE WHERE status=pending.</li>
 * </ul>
 */
@Entity
@Table(name = "record_drafts")
@EntityListeners(AuditingEntityListener.class)
public class RecordDraft {

  @Id
  @Column(name = "id", nullable = false, updatable = false)
  private UUID id;

  @Column(name = "dictionary_id", nullable = false)
  private UUID dictionaryId;

  @Column(name = "business_key", nullable = false, length = 256)
  private String businessKey;

  /** NULL для CREATE; точка истории live record для UPDATE/CLOSE. */
  @Column(name = "parent_record_id")
  private UUID parentRecordId;

  @Enumerated(EnumType.STRING)
  @Column(name = "operation", nullable = false, length = 16)
  private DraftOperation operation;

  @Type(JsonType.class)
  @Column(name = "data", columnDefinition = "jsonb")
  private JsonNode data;

  @Column(name = "geometry", columnDefinition = "geometry(Geometry, 4326)")
  private Geometry geometry;

  @Column(name = "proposed_valid_from")
  private OffsetDateTime proposedValidFrom;

  @Column(name = "proposed_valid_to")
  private OffsetDateTime proposedValidTo;

  @Enumerated(EnumType.STRING)
  @Column(name = "status", nullable = false, length = 16)
  private DraftStatus status = DraftStatus.PENDING;

  @Column(name = "maker_id", nullable = false, length = 128, updatable = false)
  private String makerId;

  @Column(name = "maker_comment", columnDefinition = "TEXT")
  private String makerComment;

  @Column(name = "submitted_at", nullable = false, updatable = false)
  private OffsetDateTime submittedAt;

  @Column(name = "reviewer_id", length = 128)
  private String reviewerId;

  @Column(name = "reviewed_at")
  private OffsetDateTime reviewedAt;

  @Column(name = "review_comment", columnDefinition = "TEXT")
  private String reviewComment;

  @Version
  @Column(name = "version")
  private Long version;

  protected RecordDraft() {}

  public RecordDraft(
      UUID id, UUID dictionaryId, String businessKey,
      DraftOperation operation, String makerId) {
    this.id = id;
    this.dictionaryId = dictionaryId;
    this.businessKey = businessKey;
    this.operation = operation;
    this.makerId = makerId;
    this.submittedAt = OffsetDateTime.now();
  }

  public UUID getId() { return id; }
  public UUID getDictionaryId() { return dictionaryId; }
  public String getBusinessKey() { return businessKey; }
  public UUID getParentRecordId() { return parentRecordId; }
  public DraftOperation getOperation() { return operation; }
  public JsonNode getData() { return data; }
  public Geometry getGeometry() { return geometry; }
  public OffsetDateTime getProposedValidFrom() { return proposedValidFrom; }
  public OffsetDateTime getProposedValidTo() { return proposedValidTo; }
  public DraftStatus getStatus() { return status; }
  public String getMakerId() { return makerId; }
  public String getMakerComment() { return makerComment; }
  public OffsetDateTime getSubmittedAt() { return submittedAt; }
  public String getReviewerId() { return reviewerId; }
  public OffsetDateTime getReviewedAt() { return reviewedAt; }
  public String getReviewComment() { return reviewComment; }
  public Long getVersion() { return version; }

  public void setParentRecordId(UUID v) { this.parentRecordId = v; }
  public void setData(JsonNode v) { this.data = v; }
  public void setGeometry(Geometry v) { this.geometry = v; }
  public void setProposedValidFrom(OffsetDateTime v) { this.proposedValidFrom = v; }
  public void setProposedValidTo(OffsetDateTime v) { this.proposedValidTo = v; }
  public void setStatus(DraftStatus v) { this.status = v; }
  public void setMakerComment(String v) { this.makerComment = v; }
  public void setReviewerId(String v) { this.reviewerId = v; }
  public void setReviewedAt(OffsetDateTime v) { this.reviewedAt = v; }
  public void setReviewComment(String v) { this.reviewComment = v; }
}
